Skip to content

Commit 1116918

Browse files
authoredFeb 1, 2020
Formspec: Create a new class for inventorylists (#9287)
1 parent 908e762 commit 1116918

File tree

8 files changed

+448
-291
lines changed

8 files changed

+448
-291
lines changed
 

Diff for: ‎build/android/jni/Android.mk

+1
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ LOCAL_SRC_FILES := \
189189
jni/src/gui/guiEngine.cpp \
190190
jni/src/gui/guiFormSpecMenu.cpp \
191191
jni/src/gui/guiHyperText.cpp \
192+
jni/src/gui/guiInventoryList.cpp \
192193
jni/src/gui/guiItemImage.cpp \
193194
jni/src/gui/guiKeyChangeMenu.cpp \
194195
jni/src/gui/guiPasswordChange.cpp \

Diff for: ‎doc/lua_api.txt

-4
Original file line numberDiff line numberDiff line change
@@ -1946,8 +1946,6 @@ For coloured text you can use `minetest.colorize`.
19461946

19471947
Since formspec version 3, elements drawn in the order they are defined. All
19481948
background elements are drawn before all other elements.
1949-
`list` elements are an exception here. They are drawn last. This, however, might
1950-
be changed at any time.
19511949

19521950
**WARNING**: do _not_ use a element name starting with `key_`; those names are
19531951
reserved to pass key press events to formspec!
@@ -2058,15 +2056,13 @@ Elements
20582056
be shown if the inventory list is of size 0.
20592057
* **Note**: With the new coordinate system, the spacing between inventory
20602058
slots is one-fourth the size of an inventory slot.
2061-
* **Note**: Lists are drawn after every other element. This might change at any time.
20622059

20632060
### `list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;<starting item index>]`
20642061

20652062
* Show an inventory list if it has been sent to the client. Nothing will
20662063
be shown if the inventory list is of size 0.
20672064
* **Note**: With the new coordinate system, the spacing between inventory
20682065
slots is one-fourth the size of an inventory slot.
2069-
* **Note**: Lists are drawn after every other element. This might change at any time.
20702066

20712067
### `listring[<inventory location>;<list name>]`
20722068

Diff for: ‎src/gui/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ set(gui_SRCS
99
${CMAKE_CURRENT_SOURCE_DIR}/guiEditBoxWithScrollbar.cpp
1010
${CMAKE_CURRENT_SOURCE_DIR}/guiEngine.cpp
1111
${CMAKE_CURRENT_SOURCE_DIR}/guiFormSpecMenu.cpp
12+
${CMAKE_CURRENT_SOURCE_DIR}/guiInventoryList.cpp
1213
${CMAKE_CURRENT_SOURCE_DIR}/guiItemImage.cpp
1314
${CMAKE_CURRENT_SOURCE_DIR}/guiKeyChangeMenu.cpp
1415
${CMAKE_CURRENT_SOURCE_DIR}/guiPasswordChange.cpp

Diff for: ‎src/gui/guiFormSpecMenu.cpp

+72-205
Large diffs are not rendered by default.

Diff for: ‎src/gui/guiFormSpecMenu.h

+32-82
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2626
#include "irrlichttypes_extrabloated.h"
2727
#include "inventorymanager.h"
2828
#include "modalMenu.h"
29+
#include "guiInventoryList.h"
2930
#include "guiTable.h"
3031
#include "network/networkprotocol.h"
3132
#include "client/joystick_controller.h"
@@ -78,51 +79,6 @@ class IFormSource
7879

7980
class GUIFormSpecMenu : public GUIModalMenu
8081
{
81-
struct ItemSpec
82-
{
83-
ItemSpec() = default;
84-
85-
ItemSpec(const InventoryLocation &a_inventoryloc,
86-
const std::string &a_listname,
87-
s32 a_i) :
88-
inventoryloc(a_inventoryloc),
89-
listname(a_listname),
90-
i(a_i)
91-
{
92-
}
93-
94-
bool isValid() const { return i != -1; }
95-
96-
InventoryLocation inventoryloc;
97-
std::string listname;
98-
s32 i = -1;
99-
};
100-
101-
struct ListDrawSpec
102-
{
103-
ListDrawSpec() = default;
104-
105-
ListDrawSpec(const InventoryLocation &a_inventoryloc,
106-
const std::string &a_listname,
107-
IGUIElement *elem, v2s32 a_geom, s32 a_start_item_i,
108-
bool a_real_coordinates):
109-
inventoryloc(a_inventoryloc),
110-
listname(a_listname),
111-
e(elem),
112-
geom(a_geom),
113-
start_item_i(a_start_item_i),
114-
real_coordinates(a_real_coordinates)
115-
{
116-
}
117-
118-
InventoryLocation inventoryloc;
119-
std::string listname;
120-
IGUIElement *e;
121-
v2s32 geom;
122-
s32 start_item_i;
123-
bool real_coordinates;
124-
};
125-
12682
struct ListRingSpec
12783
{
12884
ListRingSpec() = default;
@@ -186,35 +142,6 @@ class GUIFormSpecMenu : public GUIModalMenu
186142
irr::video::SColor color;
187143
};
188144

189-
struct StaticTextSpec
190-
{
191-
StaticTextSpec():
192-
parent_button(NULL)
193-
{
194-
}
195-
196-
StaticTextSpec(const std::wstring &a_text,
197-
const core::rect<s32> &a_rect):
198-
text(a_text),
199-
rect(a_rect),
200-
parent_button(NULL)
201-
{
202-
}
203-
204-
StaticTextSpec(const std::wstring &a_text,
205-
const core::rect<s32> &a_rect,
206-
gui::IGUIButton *a_parent_button):
207-
text(a_text),
208-
rect(a_rect),
209-
parent_button(a_parent_button)
210-
{
211-
}
212-
213-
std::wstring text;
214-
core::rect<s32> rect;
215-
gui::IGUIButton *parent_button;
216-
};
217-
218145
public:
219146
GUIFormSpecMenu(JoystickController *joystick,
220147
gui::IGUIElement* parent, s32 id,
@@ -283,13 +210,37 @@ class GUIFormSpecMenu : public GUIModalMenu
283210
m_focused_element = elementname;
284211
}
285212

213+
Client *getClient() const
214+
{
215+
return m_client;
216+
}
217+
218+
const GUIInventoryList::ItemSpec *getSelectedItem() const
219+
{
220+
return m_selected_item;
221+
}
222+
223+
const u16 getSelectedAmount() const
224+
{
225+
return m_selected_amount;
226+
}
227+
228+
bool doTooltipAppendItemname() const
229+
{
230+
return m_tooltip_append_itemname;
231+
}
232+
233+
void addHoveredItemTooltip(const std::string &name)
234+
{
235+
m_hovered_item_tooltips.emplace_back(name);
236+
}
237+
286238
/*
287239
Remove and re-add (or reposition) stuff
288240
*/
289241
void regenerateGui(v2u32 screensize);
290242

291-
ItemSpec getItemAtPos(v2s32 p) const;
292-
void drawList(const ListDrawSpec &s, int layer, bool &item_hovered);
243+
GUIInventoryList::ItemSpec getItemAtPos(v2s32 p) const;
293244
void drawSelectedItem();
294245
void drawMenu();
295246
void updateSelectedItem();
@@ -342,7 +293,7 @@ class GUIFormSpecMenu : public GUIModalMenu
342293
std::string m_formspec_prepend;
343294
InventoryLocation m_current_inventory_location;
344295

345-
std::vector<ListDrawSpec> m_inventorylists;
296+
std::vector<GUIInventoryList *> m_inventorylists;
346297
std::vector<ListRingSpec> m_inventory_rings;
347298
std::vector<gui::IGUIElement *> m_backgrounds;
348299
std::unordered_map<std::string, bool> field_close_on_enter;
@@ -354,7 +305,7 @@ class GUIFormSpecMenu : public GUIModalMenu
354305
std::vector<std::pair<FieldSpec, GUIScrollBar *>> m_scrollbars;
355306
std::vector<std::pair<FieldSpec, std::vector<std::string>>> m_dropdowns;
356307

357-
ItemSpec *m_selected_item = nullptr;
308+
GUIInventoryList::ItemSpec *m_selected_item = nullptr;
358309
u16 m_selected_amount = 0;
359310
bool m_selected_dragging = false;
360311
ItemStack m_selected_swap;
@@ -374,12 +325,8 @@ class GUIFormSpecMenu : public GUIModalMenu
374325

375326
bool m_bgnonfullscreen;
376327
bool m_bgfullscreen;
377-
bool m_slotborder;
378328
video::SColor m_bgcolor;
379329
video::SColor m_fullscreen_bgcolor;
380-
video::SColor m_slotbg_n;
381-
video::SColor m_slotbg_h;
382-
video::SColor m_slotbordercolor;
383330
video::SColor m_default_tooltip_bgcolor;
384331
video::SColor m_default_tooltip_color;
385332

@@ -406,6 +353,8 @@ class GUIFormSpecMenu : public GUIModalMenu
406353
GUITable::TableOptions table_options;
407354
GUITable::TableColumns table_columns;
408355

356+
GUIInventoryList::Options inventorylist_options;
357+
409358
struct {
410359
s32 max = 1000;
411360
s32 min = 0;
@@ -428,6 +377,7 @@ class GUIFormSpecMenu : public GUIModalMenu
428377

429378
fs_key_pendig current_keys_pending;
430379
std::string current_field_enter_pending = "";
380+
std::vector<std::string> m_hovered_item_tooltips;
431381

432382
void parseElement(parserData* data, const std::string &element);
433383

Diff for: ‎src/gui/guiInventoryList.cpp

+210
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
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+
}

Diff for: ‎src/gui/guiInventoryList.h

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
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+
#pragma once
21+
22+
#include "inventorymanager.h"
23+
#include "irrlichttypes_extrabloated.h"
24+
#include "util/string.h"
25+
26+
class GUIFormSpecMenu;
27+
28+
class GUIInventoryList : public gui::IGUIElement
29+
{
30+
public:
31+
struct ItemSpec
32+
{
33+
ItemSpec() = default;
34+
35+
ItemSpec(const InventoryLocation &a_inventoryloc,
36+
const std::string &a_listname,
37+
s32 a_i) :
38+
inventoryloc(a_inventoryloc),
39+
listname(a_listname),
40+
i(a_i)
41+
{
42+
}
43+
44+
bool isValid() const { return i != -1; }
45+
46+
InventoryLocation inventoryloc;
47+
std::string listname;
48+
s32 i = -1;
49+
};
50+
51+
// options for inventorylists that are setable with the lua api
52+
struct Options {
53+
// whether a one-pixel border for the slots should be drawn and its color
54+
bool slotborder = false;
55+
video::SColor slotbordercolor = video::SColor(200, 0, 0, 0);
56+
// colors for normal and highlighted slot background
57+
video::SColor slotbg_n = video::SColor(255, 128, 128, 128);
58+
video::SColor slotbg_h = video::SColor(255, 192, 192, 192);
59+
};
60+
61+
GUIInventoryList(gui::IGUIEnvironment *env,
62+
gui::IGUIElement *parent,
63+
s32 id,
64+
const core::rect<s32> &rectangle,
65+
InventoryManager *invmgr,
66+
const InventoryLocation &inventoryloc,
67+
const std::string &listname,
68+
const v2s32 &geom,
69+
const s32 start_item_i,
70+
const v2s32 &slot_size,
71+
const v2f32 &slot_spacing,
72+
GUIFormSpecMenu *fs_menu,
73+
const Options &options,
74+
gui::IGUIFont *font);
75+
76+
virtual void draw() override;
77+
78+
virtual bool OnEvent(const SEvent &event) override;
79+
80+
const InventoryLocation &getInventoryloc() const
81+
{
82+
return m_inventoryloc;
83+
}
84+
85+
const std::string &getListname() const
86+
{
87+
return m_listname;
88+
}
89+
90+
void setSlotBGColors(const video::SColor &slotbg_n, const video::SColor &slotbg_h)
91+
{
92+
m_options.slotbg_n = slotbg_n;
93+
m_options.slotbg_h = slotbg_h;
94+
}
95+
96+
void setSlotBorders(bool slotborder, const video::SColor &slotbordercolor)
97+
{
98+
m_options.slotborder = slotborder;
99+
m_options.slotbordercolor = slotbordercolor;
100+
}
101+
102+
// returns -1 if not item is at pos p
103+
s32 getItemIndexAtPos(v2s32 p) const;
104+
105+
private:
106+
InventoryManager *m_invmgr;
107+
const InventoryLocation m_inventoryloc;
108+
const std::string m_listname;
109+
110+
// specifies the width and height of the inventorylist in itemslots
111+
const v2s32 m_geom;
112+
// the first item's index in inventory
113+
const s32 m_start_item_i;
114+
115+
// specifies how large the slot rects are
116+
const v2s32 m_slot_size;
117+
// specifies how large the space between slots is (space between is spacing-size)
118+
const v2f32 m_slot_spacing;
119+
120+
// the GUIFormSpecMenu can have an item selected and co.
121+
GUIFormSpecMenu *m_fs_menu;
122+
123+
Options m_options;
124+
125+
// the font
126+
gui::IGUIFont *m_font;
127+
128+
// the index of the hovered item; -1 if no item is hovered
129+
s32 m_hovered_i;
130+
};

Diff for: ‎util/travis/clang-format-whitelist.txt

+2
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ src/gui/guiFormSpecMenu.h
177177
src/gui/guiKeyChangeMenu.cpp
178178
src/gui/guiHyperText.cpp
179179
src/gui/guiHyperText.h
180+
src/gui/guiInventoryList.cpp
181+
src/gui/guiInventoryList.h
180182
src/gui/guiItemImage.cpp
181183
src/gui/guiItemImage.h
182184
src/gui/guiMainMenu.h

0 commit comments

Comments
 (0)
Please sign in to comment.