summaryrefslogtreecommitdiff
path: root/src/gui/guiInventoryList.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/guiInventoryList.cpp')
-rw-r--r--src/gui/guiInventoryList.cpp210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/gui/guiInventoryList.cpp b/src/gui/guiInventoryList.cpp
new file mode 100644
index 000000000..ae7ec0539
--- /dev/null
+++ b/src/gui/guiInventoryList.cpp
@@ -0,0 +1,210 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "guiInventoryList.h"
+#include "guiFormSpecMenu.h"
+#include "client/hud.h"
+#include "client/client.h"
+
+GUIInventoryList::GUIInventoryList(gui::IGUIEnvironment *env,
+ gui::IGUIElement *parent,
+ s32 id,
+ const core::rect<s32> &rectangle,
+ InventoryManager *invmgr,
+ const InventoryLocation &inventoryloc,
+ const std::string &listname,
+ const v2s32 &geom,
+ const s32 start_item_i,
+ const v2s32 &slot_size,
+ const v2f32 &slot_spacing,
+ GUIFormSpecMenu *fs_menu,
+ const Options &options,
+ gui::IGUIFont *font) :
+ gui::IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rectangle),
+ m_invmgr(invmgr),
+ m_inventoryloc(inventoryloc),
+ m_listname(listname),
+ m_geom(geom),
+ m_start_item_i(start_item_i),
+ m_slot_size(slot_size),
+ m_slot_spacing(slot_spacing),
+ m_fs_menu(fs_menu),
+ m_options(options),
+ m_font(font),
+ m_hovered_i(-1)
+{
+}
+
+void GUIInventoryList::draw()
+{
+ if (!IsVisible)
+ return;
+
+ Inventory *inv = m_invmgr->getInventory(m_inventoryloc);
+ if (!inv) {
+ warningstream << "GUIInventoryList::draw(): "
+ << "The inventory location "
+ << "\"" << m_inventoryloc.dump() << "\" doesn't exist anymore"
+ << std::endl;
+ return;
+ }
+ InventoryList *ilist = inv->getList(m_listname);
+ if (!ilist) {
+ warningstream << "GUIInventoryList::draw(): "
+ << "The inventory list \"" << m_listname << "\" @ \""
+ << m_inventoryloc.dump() << "\" doesn't exist anymore"
+ << std::endl;
+ return;
+ }
+
+ video::IVideoDriver *driver = Environment->getVideoDriver();
+ Client *client = m_fs_menu->getClient();
+ const ItemSpec *selected_item = m_fs_menu->getSelectedItem();
+
+ core::rect<s32> imgrect(0, 0, m_slot_size.X, m_slot_size.Y);
+ v2s32 base_pos = AbsoluteRect.UpperLeftCorner;
+
+ for (s32 i = 0; i < m_geom.X * m_geom.Y; i++) {
+ s32 item_i = i + m_start_item_i;
+ if (item_i >= (s32)ilist->getSize())
+ break;
+
+ v2s32 p((i % m_geom.X) * m_slot_spacing.X,
+ (i / m_geom.X) * m_slot_spacing.Y);
+ core::rect<s32> rect = imgrect + base_pos + p;
+ ItemStack item = ilist->getItem(item_i);
+
+ bool selected = selected_item
+ && m_invmgr->getInventory(selected_item->inventoryloc) == inv
+ && selected_item->listname == m_listname
+ && selected_item->i == item_i;
+ core::rect<s32> clipped_rect(rect);
+ clipped_rect.clipAgainst(AbsoluteClippingRect);
+ bool hovering = m_hovered_i == item_i;
+ ItemRotationKind rotation_kind = selected ? IT_ROT_SELECTED :
+ (hovering ? IT_ROT_HOVERED : IT_ROT_NONE);
+
+ // layer 0
+ if (hovering) {
+ driver->draw2DRectangle(m_options.slotbg_h, rect, &AbsoluteClippingRect);
+ } else {
+ driver->draw2DRectangle(m_options.slotbg_n, rect, &AbsoluteClippingRect);
+ }
+
+ // Draw inv slot borders
+ if (m_options.slotborder) {
+ s32 x1 = rect.UpperLeftCorner.X;
+ s32 y1 = rect.UpperLeftCorner.Y;
+ s32 x2 = rect.LowerRightCorner.X;
+ s32 y2 = rect.LowerRightCorner.Y;
+ s32 border = 1;
+ core::rect<s32> clipping_rect = Parent ? Parent->getAbsoluteClippingRect()
+ : core::rect<s32>();
+ core::rect<s32> *clipping_rect_ptr = Parent ? &clipping_rect : nullptr;
+ driver->draw2DRectangle(m_options.slotbordercolor,
+ core::rect<s32>(v2s32(x1 - border, y1 - border),
+ v2s32(x2 + border, y1)), clipping_rect_ptr);
+ driver->draw2DRectangle(m_options.slotbordercolor,
+ core::rect<s32>(v2s32(x1 - border, y2),
+ v2s32(x2 + border, y2 + border)), clipping_rect_ptr);
+ driver->draw2DRectangle(m_options.slotbordercolor,
+ core::rect<s32>(v2s32(x1 - border, y1),
+ v2s32(x1, y2)), clipping_rect_ptr);
+ driver->draw2DRectangle(m_options.slotbordercolor,
+ core::rect<s32>(v2s32(x2, y1),
+ v2s32(x2 + border, y2)), clipping_rect_ptr);
+ }
+
+ // layer 1
+ if (selected)
+ item.takeItem(m_fs_menu->getSelectedAmount());
+
+ if (!item.empty()) {
+ // Draw item stack
+ drawItemStack(driver, m_font, item, rect, &AbsoluteClippingRect,
+ client, rotation_kind);
+ // Add hovering tooltip
+ if (hovering && !selected_item) {
+ std::string tooltip = item.getDescription(client->idef());
+ if (m_fs_menu->doTooltipAppendItemname())
+ tooltip += "\n[" + item.name + "]";
+ m_fs_menu->addHoveredItemTooltip(tooltip);
+ }
+ }
+ }
+
+ IGUIElement::draw();
+}
+
+bool GUIInventoryList::OnEvent(const SEvent &event)
+{
+ if (event.EventType != EET_MOUSE_INPUT_EVENT) {
+ if (event.EventType == EET_GUI_EVENT &&
+ event.GUIEvent.EventType == EGET_ELEMENT_LEFT) {
+ // element is no longer hovered
+ m_hovered_i = -1;
+ }
+ return IGUIElement::OnEvent(event);
+ }
+
+ m_hovered_i = getItemIndexAtPos(v2s32(event.MouseInput.X, event.MouseInput.Y));
+
+ if (m_hovered_i != -1)
+ return IGUIElement::OnEvent(event);
+
+ // no item slot at pos of mouse event => allow clicking through
+ // find the element that would be hovered if this inventorylist was invisible
+ bool was_visible = IsVisible;
+ IsVisible = false;
+ IGUIElement *hovered =
+ Environment->getRootGUIElement()->getElementFromPoint(
+ core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
+
+ bool ret = hovered && hovered->OnEvent(event);
+
+ IsVisible = was_visible;
+
+ return ret;
+}
+
+s32 GUIInventoryList::getItemIndexAtPos(v2s32 p) const
+{
+ if (!IsVisible || AbsoluteClippingRect.getArea() <= 0 ||
+ !AbsoluteClippingRect.isPointInside(p))
+ return -1;
+
+ core::rect<s32> imgrect(0, 0, m_slot_size.X, m_slot_size.Y);
+ v2s32 base_pos = AbsoluteRect.UpperLeftCorner;
+
+ // instead of looping through each slot, we look where p would be in the grid
+ s32 i = (p.X - base_pos.X) / (s32)m_slot_spacing.X
+ + m_geom.X * ((p.Y - base_pos.Y) / (s32)m_slot_spacing.Y);
+
+ v2s32 p0((i % m_geom.X) * m_slot_spacing.X,
+ (i / m_geom.X) * m_slot_spacing.Y);
+
+ core::rect<s32> rect = imgrect + base_pos + p0;
+
+ rect.clipAgainst(AbsoluteClippingRect);
+
+ if (rect.getArea() > 0 && rect.isPointInside(p))
+ return i + m_start_item_i;
+
+ return -1;
+}