]> git.lizzy.rs Git - dragonfireclient.git/blob - src/hud.cpp
Merge remote branch 'origin/master'
[dragonfireclient.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                                 driver->draw2DImage(texture, rect,
190                                         core::rect<s32>(core::position2d<s32>(0,0), imgsize),
191                                         NULL, colors, true);
192                                 break; }
193                         case HUD_ELEM_TEXT: {
194                                 video::SColor color(255, (e->number >> 16) & 0xFF,
195                                                                                  (e->number >> 8)  & 0xFF,
196                                                                                  (e->number >> 0)  & 0xFF);
197                                 core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
198                                 font->draw(narrow_to_wide(e->text).c_str(), size + pos, color);
199                                 break; }
200                         case HUD_ELEM_STATBAR:
201                                 drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number);
202                                 break;
203                         case HUD_ELEM_INVENTORY: {
204                                 InventoryList *inv = inventory->getList(e->text);
205                                 drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir);
206                                 break; }
207                         default:
208                                 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
209                                         "of hud element ID " << i << " due to unrecognized type" << std::endl;
210                 }
211         }
212 }
213
214
215 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count) {
216         const video::SColor color(255, 255, 255, 255);
217         const video::SColor colors[] = {color, color, color, color};
218         
219         video::ITexture *stat_texture =
220                 gamedef->getTextureSource()->getTextureRaw(texture);
221         if (!stat_texture)
222                 return;
223                 
224         core::dimension2di srcd(stat_texture->getOriginalSize());
225
226         v2s32 p = pos;
227         if (corner & HUD_CORNER_LOWER)
228                 p -= srcd.Height;
229
230         v2s32 steppos;
231         switch (drawdir) {
232                 case HUD_DIR_RIGHT_LEFT:
233                         steppos = v2s32(-1, 0);
234                         break;
235                 case HUD_DIR_TOP_BOTTOM:
236                         steppos = v2s32(0, 1);
237                         break;
238                 case HUD_DIR_BOTTOM_TOP:
239                         steppos = v2s32(0, -1);
240                         break;
241                 default:
242                         steppos = v2s32(1, 0);  
243         }
244         steppos.X *= srcd.Width;
245         steppos.Y *= srcd.Height;
246         
247         for (s32 i = 0; i < count / 2; i++)
248         {
249                 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
250                 core::rect<s32> dstrect(srcrect);
251
252                 dstrect += p;
253                 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
254                 p += steppos;
255         }
256         
257         if (count % 2 == 1)
258         {
259                 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
260                 core::rect<s32> dstrect(srcrect);
261
262                 dstrect += p;
263                 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
264         }
265 }
266
267
268 void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
269         InventoryList *mainlist = inventory->getList("main");
270         if (mainlist == NULL) {
271                 errorstream << "draw_hotbar(): mainlist == NULL" << std::endl;
272                 return;
273         }
274         
275         s32 padding = hotbar_imagesize / 12;
276         s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2);
277         v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2);
278         
279         drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0);
280         drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT,
281                                 "heart.png", halfheartcount);
282 }
283
284
285 void Hud::drawCrosshair() {
286         driver->draw2DLine(displaycenter - v2s32(10, 0),
287                         displaycenter + v2s32(10, 0), crosshair_argb);
288         driver->draw2DLine(displaycenter - v2s32(0, 10),
289                         displaycenter + v2s32(0, 10), crosshair_argb);
290 }
291
292
293 void Hud::drawSelectionBoxes(std::vector<aabb3f> &hilightboxes) {
294         for (std::vector<aabb3f>::const_iterator
295                         i = hilightboxes.begin();
296                         i != hilightboxes.end(); i++) {
297                 driver->draw3DBox(*i, selectionbox_argb);
298         }
299 }
300
301
302 void Hud::resizeHotbar() {
303         if (screensize.Y <= 800)
304                 hotbar_imagesize = 32;
305         else if (screensize.Y <= 1280)
306                 hotbar_imagesize = 48;
307         else
308                 hotbar_imagesize = 64;
309 }