]> git.lizzy.rs Git - minetest.git/blob - src/hud.cpp
Remove texture atlas / AtlasPointer, rename getTextureRaw to getTexture
[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         
47         tsrc = gamedef->getTextureSource();
48         
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);
55         
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);
61         
62         use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
63 }
64
65
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)
69 {
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);
76         }
77         s32 fullimglen = imgsize + padding * 2;
78
79         // Position of upper left corner of bar
80         v2s32 pos = upperleftpos;
81
82         // Draw background color
83         /*core::rect<s32> barrect(0,0,width,height);
84         barrect += pos;
85         video::SColor bgcolor(255,128,128,128);
86         driver->draw2DRectangle(bgcolor, barrect, NULL);*/
87
88         core::rect<s32> imgrect(0, 0, imgsize, imgsize);
89
90         for (s32 i = 0; i < itemcount; i++)
91         {
92                 const ItemStack &item = mainlist->getItem(i);
93
94                 v2s32 steppos;
95                 switch (direction) {
96                         case HUD_DIR_RIGHT_LEFT:
97                                 steppos = v2s32(-(padding + i * fullimglen), padding);
98                                 break;
99                         case HUD_DIR_TOP_BOTTOM:
100                                 steppos = v2s32(padding, padding + i * fullimglen);
101                                 break;
102                         case HUD_DIR_BOTTOM_TOP:
103                                 steppos = v2s32(padding, -(padding + i * fullimglen));
104                                 break;
105                         default:
106                                 steppos = v2s32(padding + i * fullimglen, padding);     
107                 }
108                         
109                 core::rect<s32> rect = imgrect + pos + steppos;
110
111                 if (selectitem == i + 1)
112                 {
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,
122                                         core::rect<s32>(
123                                                 v2s32(x1 - padding, y1 - padding),
124                                                 v2s32(x2 + padding, y1)
125                                         ), NULL);
126                         driver->draw2DRectangle(c_outside,
127                                         core::rect<s32>(
128                                                 v2s32(x1 - padding, y2),
129                                                 v2s32(x2 + padding, y2 + padding)
130                                         ), NULL);
131                         driver->draw2DRectangle(c_outside,
132                                         core::rect<s32>(
133                                                 v2s32(x1 - padding, y1),
134                                                 v2s32(x1, y2)
135                                         ), NULL);
136                         driver->draw2DRectangle(c_outside,
137                                         core::rect<s32>(
138                                                 v2s32(x2, y1),
139                                                 v2s32(x2 + padding, y2)
140                                         ), NULL);
141                         /*// Light inside borders
142                         driver->draw2DRectangle(c_inside,
143                                         core::rect<s32>(
144                                                 v2s32(x1 - padding/2, y1 - padding/2),
145                                                 v2s32(x2 + padding/2, y1)
146                                         ), NULL);
147                         driver->draw2DRectangle(c_inside,
148                                         core::rect<s32>(
149                                                 v2s32(x1 - padding/2, y2),
150                                                 v2s32(x2 + padding/2, y2 + padding/2)
151                                         ), NULL);
152                         driver->draw2DRectangle(c_inside,
153                                         core::rect<s32>(
154                                                 v2s32(x1 - padding/2, y1),
155                                                 v2s32(x1, y2)
156                                         ), NULL);
157                         driver->draw2DRectangle(c_inside,
158                                         core::rect<s32>(
159                                                 v2s32(x2, y1),
160                                                 v2s32(x2 + padding/2, y2)
161                                         ), NULL);
162                         */
163                 }
164
165                 video::SColor bgcolor2(128, 0, 0, 0);
166                 driver->draw2DRectangle(bgcolor2, rect, NULL);
167                 drawItemStack(driver, font, item, rect, NULL, gamedef);
168         }
169 }
170
171
172 void Hud::drawLuaElements() {
173         for (size_t i = 0; i != player->hud.size(); i++) {
174                 HudElement *e = player->hud[i];
175                 if (!e)
176                         continue;
177                 
178                 v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y);
179                 switch (e->type) {
180                         case HUD_ELEM_IMAGE: {
181                                 video::ITexture *texture = tsrc->getTexture(e->text);
182                                 if (!texture)
183                                         continue;
184
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);
190                                 rect += pos;
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));
193                                 rect += offset;
194                                 rect += v2s32(e->offset.X, e->offset.Y);
195                                 driver->draw2DImage(texture, rect,
196                                         core::rect<s32>(core::position2d<s32>(0,0), imgsize),
197                                         NULL, colors, true);
198                                 break; }
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);
210                                 break; }
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);
214                                 break; }
215                         case HUD_ELEM_INVENTORY: {
216                                 InventoryList *inv = inventory->getList(e->text);
217                                 drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir);
218                                 break; }
219                         default:
220                                 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
221                                         "of hud element ID " << i << " due to unrecognized type" << std::endl;
222                 }
223         }
224 }
225
226
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};
230         
231         video::ITexture *stat_texture = tsrc->getTexture(texture);
232         if (!stat_texture)
233                 return;
234                 
235         core::dimension2di srcd(stat_texture->getOriginalSize());
236
237         v2s32 p = pos;
238         if (corner & HUD_CORNER_LOWER)
239                 p -= srcd.Height;
240
241         p += offset;
242
243         v2s32 steppos;
244         switch (drawdir) {
245                 case HUD_DIR_RIGHT_LEFT:
246                         steppos = v2s32(-1, 0);
247                         break;
248                 case HUD_DIR_TOP_BOTTOM:
249                         steppos = v2s32(0, 1);
250                         break;
251                 case HUD_DIR_BOTTOM_TOP:
252                         steppos = v2s32(0, -1);
253                         break;
254                 default:
255                         steppos = v2s32(1, 0);  
256         }
257         steppos.X *= srcd.Width;
258         steppos.Y *= srcd.Height;
259         
260         for (s32 i = 0; i < count / 2; i++)
261         {
262                 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
263                 core::rect<s32> dstrect(srcrect);
264
265                 dstrect += p;
266                 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
267                 p += steppos;
268         }
269         
270         if (count % 2 == 1)
271         {
272                 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
273                 core::rect<s32> dstrect(srcrect);
274
275                 dstrect += p;
276                 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
277         }
278 }
279
280
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;
285                 return;
286         }
287         
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);
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         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));
301 }
302
303
304 void Hud::drawCrosshair() {
305         if (!(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE))
306                 return;
307                 
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);
316         } else {
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);
321         }
322 }
323
324
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);
330         }
331 }
332
333
334 void Hud::resizeHotbar() {
335         if (screensize.Y <= 800)
336                 hotbar_imagesize = 32;
337         else if (screensize.Y <= 1280)
338                 hotbar_imagesize = 48;
339         else
340                 hotbar_imagesize = 64;
341 }