]> git.lizzy.rs Git - dragonfireclient.git/blob - src/gui/guiInventoryList.cpp
Add limit parameter to decompressZlib
[dragonfireclient.git] / src / gui / guiInventoryList.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "guiInventoryList.h"
21 #include "guiFormSpecMenu.h"
22 #include "client/hud.h"
23 #include "client/client.h"
24
25 GUIInventoryList::GUIInventoryList(gui::IGUIEnvironment *env,
26         gui::IGUIElement *parent,
27         s32 id,
28         const core::rect<s32> &rectangle,
29         InventoryManager *invmgr,
30         const InventoryLocation &inventoryloc,
31         const std::string &listname,
32         const v2s32 &geom,
33         const s32 start_item_i,
34         const v2s32 &slot_size,
35         const v2f32 &slot_spacing,
36         GUIFormSpecMenu *fs_menu,
37         const Options &options,
38         gui::IGUIFont *font) :
39         gui::IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rectangle),
40         m_invmgr(invmgr),
41         m_inventoryloc(inventoryloc),
42         m_listname(listname),
43         m_geom(geom),
44         m_start_item_i(start_item_i),
45         m_slot_size(slot_size),
46         m_slot_spacing(slot_spacing),
47         m_fs_menu(fs_menu),
48         m_options(options),
49         m_font(font),
50         m_hovered_i(-1)
51 {
52 }
53
54 void GUIInventoryList::draw()
55 {
56         if (!IsVisible)
57                 return;
58
59         Inventory *inv = m_invmgr->getInventory(m_inventoryloc);
60         if (!inv) {
61                 warningstream << "GUIInventoryList::draw(): "
62                                 << "The inventory location "
63                                 << "\"" << m_inventoryloc.dump() << "\" doesn't exist anymore"
64                                 << std::endl;
65                 return;
66         }
67         InventoryList *ilist = inv->getList(m_listname);
68         if (!ilist) {
69                 warningstream << "GUIInventoryList::draw(): "
70                                 << "The inventory list \"" << m_listname << "\" @ \""
71                                 << m_inventoryloc.dump() << "\" doesn't exist anymore"
72                                 << std::endl;
73                 return;
74         }
75
76         video::IVideoDriver *driver = Environment->getVideoDriver();
77         Client *client = m_fs_menu->getClient();
78         const ItemSpec *selected_item = m_fs_menu->getSelectedItem();
79
80         core::rect<s32> imgrect(0, 0, m_slot_size.X, m_slot_size.Y);
81         v2s32 base_pos = AbsoluteRect.UpperLeftCorner;
82
83         for (s32 i = 0; i < m_geom.X * m_geom.Y; i++) {
84                 s32 item_i = i + m_start_item_i;
85                 if (item_i >= (s32)ilist->getSize())
86                         break;
87
88                 v2s32 p((i % m_geom.X) * m_slot_spacing.X,
89                                 (i / m_geom.X) * m_slot_spacing.Y);
90                 core::rect<s32> rect = imgrect + base_pos + p;
91                 ItemStack item = ilist->getItem(item_i);
92
93                 bool selected = selected_item
94                         && m_invmgr->getInventory(selected_item->inventoryloc) == inv
95                         && selected_item->listname == m_listname
96                         && selected_item->i == item_i;
97                 core::rect<s32> clipped_rect(rect);
98                 clipped_rect.clipAgainst(AbsoluteClippingRect);
99                 bool hovering = m_hovered_i == item_i;
100                 ItemRotationKind rotation_kind = selected ? IT_ROT_SELECTED :
101                         (hovering ? IT_ROT_HOVERED : IT_ROT_NONE);
102
103                 // layer 0
104                 if (hovering) {
105                         driver->draw2DRectangle(m_options.slotbg_h, rect, &AbsoluteClippingRect);
106                 } else {
107                         driver->draw2DRectangle(m_options.slotbg_n, rect, &AbsoluteClippingRect);
108                 }
109
110                 // Draw inv slot borders
111                 if (m_options.slotborder) {
112                         s32 x1 = rect.UpperLeftCorner.X;
113                         s32 y1 = rect.UpperLeftCorner.Y;
114                         s32 x2 = rect.LowerRightCorner.X;
115                         s32 y2 = rect.LowerRightCorner.Y;
116                         s32 border = 1;
117                         core::rect<s32> clipping_rect = Parent ? Parent->getAbsoluteClippingRect()
118                                         : core::rect<s32>();
119                         core::rect<s32> *clipping_rect_ptr = Parent ? &clipping_rect : nullptr;
120                         driver->draw2DRectangle(m_options.slotbordercolor,
121                                 core::rect<s32>(v2s32(x1 - border, y1 - border),
122                                                                 v2s32(x2 + border, y1)), clipping_rect_ptr);
123                         driver->draw2DRectangle(m_options.slotbordercolor,
124                                 core::rect<s32>(v2s32(x1 - border, y2),
125                                                                 v2s32(x2 + border, y2 + border)), clipping_rect_ptr);
126                         driver->draw2DRectangle(m_options.slotbordercolor,
127                                 core::rect<s32>(v2s32(x1 - border, y1),
128                                                                 v2s32(x1, y2)), clipping_rect_ptr);
129                         driver->draw2DRectangle(m_options.slotbordercolor,
130                                 core::rect<s32>(v2s32(x2, y1),
131                                                                 v2s32(x2 + border, y2)), clipping_rect_ptr);
132                 }
133
134                 // layer 1
135                 if (selected)
136                         item.takeItem(m_fs_menu->getSelectedAmount());
137
138                 if (!item.empty()) {
139                         // Draw item stack
140                         drawItemStack(driver, m_font, item, rect, &AbsoluteClippingRect,
141                                         client, rotation_kind);
142                         // Add hovering tooltip
143                         if (hovering && !selected_item) {
144                                 std::string tooltip = item.getDescription(client->idef());
145                                 if (m_fs_menu->doTooltipAppendItemname())
146                                         tooltip += "\n[" + item.name + "]";
147                                 m_fs_menu->addHoveredItemTooltip(tooltip);
148                         }
149                 }
150         }
151
152         IGUIElement::draw();
153 }
154
155 bool GUIInventoryList::OnEvent(const SEvent &event)
156 {
157         if (event.EventType != EET_MOUSE_INPUT_EVENT) {
158                 if (event.EventType == EET_GUI_EVENT &&
159                                 event.GUIEvent.EventType == EGET_ELEMENT_LEFT) {
160                         // element is no longer hovered
161                         m_hovered_i = -1;
162                 }
163                 return IGUIElement::OnEvent(event);
164         }
165
166         m_hovered_i = getItemIndexAtPos(v2s32(event.MouseInput.X, event.MouseInput.Y));
167
168         if (m_hovered_i != -1)
169                 return IGUIElement::OnEvent(event);
170
171         // no item slot at pos of mouse event => allow clicking through
172         // find the element that would be hovered if this inventorylist was invisible
173         bool was_visible = IsVisible;
174         IsVisible = false;
175         IGUIElement *hovered =
176                 Environment->getRootGUIElement()->getElementFromPoint(
177                         core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
178
179         bool ret = hovered && hovered->OnEvent(event);
180
181         IsVisible = was_visible;
182
183         return ret;
184 }
185
186 s32 GUIInventoryList::getItemIndexAtPos(v2s32 p) const
187 {
188         if (!IsVisible || AbsoluteClippingRect.getArea() <= 0 ||
189                         !AbsoluteClippingRect.isPointInside(p))
190                 return -1;
191
192         core::rect<s32> imgrect(0, 0, m_slot_size.X, m_slot_size.Y);
193         v2s32 base_pos = AbsoluteRect.UpperLeftCorner;
194
195         // instead of looping through each slot, we look where p would be in the grid
196         s32 i = (p.X - base_pos.X) / (s32)m_slot_spacing.X
197                         + m_geom.X * ((p.Y - base_pos.Y) / (s32)m_slot_spacing.Y);
198
199         v2s32 p0((i % m_geom.X) * m_slot_spacing.X,
200                         (i / m_geom.X) * m_slot_spacing.Y);
201
202         core::rect<s32> rect = imgrect + base_pos + p0;
203
204         rect.clipAgainst(AbsoluteClippingRect);
205
206         if (rect.getArea() > 0 && rect.isPointInside(p))
207                 return i + m_start_item_i;
208
209         return -1;
210 }