]> git.lizzy.rs Git - dragonfireclient.git/blob - src/guiInventoryMenu.cpp
crafting system!
[dragonfireclient.git] / src / guiInventoryMenu.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010 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 General Public License as published by
7 the Free Software Foundation; either version 2 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 General Public License for more details.
14
15 You should have received a copy of the GNU 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
21 #include "guiInventoryMenu.h"
22 #include "constants.h"
23
24 void drawInventoryItem(gui::IGUIEnvironment* env,
25                 InventoryItem *item, core::rect<s32> rect,
26                 const core::rect<s32> *clip)
27 {
28         gui::IGUISkin* skin = env->getSkin();
29         if (!skin)
30                 return;
31         video::IVideoDriver* driver = env->getVideoDriver();
32         
33         video::ITexture *texture = NULL;
34         
35         if(item != NULL)
36         {
37                 texture = item->getImage();
38         }
39
40         if(texture != NULL)
41         {
42                 const video::SColor color(255,255,255,255);
43                 const video::SColor colors[] = {color,color,color,color};
44                 driver->draw2DImage(texture, rect,
45                         core::rect<s32>(core::position2d<s32>(0,0),
46                         core::dimension2di(texture->getOriginalSize())),
47                         clip, colors, false);
48         }
49         else
50         {
51                 video::SColor bgcolor(128,128,128,128);
52                 driver->draw2DRectangle(bgcolor, rect, clip);
53         }
54
55         if(item != NULL)
56         {
57                 gui::IGUIFont *font = skin->getFont();
58                 std::string text = item->getText();
59                 if(font && text != "")
60                 {
61                         core::rect<s32> rect2(rect.UpperLeftCorner,
62                                         (core::dimension2d<u32>(rect.getWidth(), 15)));
63
64                         video::SColor bgcolor(128,0,0,0);
65                         driver->draw2DRectangle(bgcolor, rect2, clip);
66
67                         font->draw(text.c_str(), rect2,
68                                         video::SColor(255,255,255,255), false, false,
69                                         clip);
70                 }
71         }
72 }
73
74 /*
75         GUIInventoryMenu
76 */
77
78 GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env,
79                 gui::IGUIElement* parent, s32 id,
80                 Inventory *inventory):
81         IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
82                         core::rect<s32>(0,0,100,100))
83 {
84         m_inventory = inventory;
85         m_screensize_old = v2u32(0,0);
86         m_selected_item = NULL;
87
88         resizeGui();
89
90         setVisible(false);
91
92         /*m_selected_item = new ItemSpec;
93         m_selected_item->listname = "main";
94         m_selected_item->i = 3;*/
95 }
96
97 GUIInventoryMenu::~GUIInventoryMenu()
98 {
99         if(m_selected_item)
100                 delete m_selected_item;
101 }
102
103 void GUIInventoryMenu::resizeGui()
104 {
105         video::IVideoDriver* driver = Environment->getVideoDriver();
106         v2u32 screensize = driver->getScreenSize();
107         if(screensize == m_screensize_old)
108                 return;
109         m_screensize_old = screensize;
110
111         padding = v2s32(24,24);
112         spacing = v2s32(60,56);
113         imgsize = v2s32(48,48);
114
115         v2s32 size(
116                 padding.X*2+spacing.X*(8-1)+imgsize.X,
117                 padding.Y*2+spacing.Y*(7-1)+imgsize.Y
118         );
119
120         core::rect<s32> rect(
121                         screensize.X/2 - size.X/2,
122                         screensize.Y/2 - size.Y/2,
123                         screensize.X/2 + size.X/2,
124                         screensize.Y/2 + size.Y/2
125         );
126         
127         DesiredRect = rect;
128         recalculateAbsolutePosition(false);
129
130         v2s32 basepos = getBasePos();
131         
132         m_draw_positions.clear();
133         m_draw_positions.push_back(ListDrawSpec("main",
134                         basepos + v2s32(spacing.X*0, spacing.Y*3), v2s32(8, 4)));
135         m_draw_positions.push_back(ListDrawSpec("craft",
136                         basepos + v2s32(spacing.X*3, spacing.Y*0), v2s32(3, 3)));
137         m_draw_positions.push_back(ListDrawSpec("craftresult",
138                         basepos + v2s32(spacing.X*7, spacing.Y*1), v2s32(1, 1)));
139 }
140
141 GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const
142 {
143         core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
144         
145         for(u32 i=0; i<m_draw_positions.size(); i++)
146         {
147                 const ListDrawSpec &s = m_draw_positions[i];
148
149                 for(s32 i=0; i<s.geom.X*s.geom.Y; i++)
150                 {
151                         s32 x = (i%s.geom.X) * spacing.X;
152                         s32 y = (i/s.geom.X) * spacing.Y;
153                         v2s32 p0(x,y);
154                         core::rect<s32> rect = imgrect + s.pos + p0;
155                         if(rect.isPointInside(p))
156                         {
157                                 return ItemSpec(s.listname, i);
158                         }
159                 }
160         }
161
162         return ItemSpec("", -1);
163 }
164
165 //void GUIInventoryMenu::drawList(const std::string &name, v2s32 pos, v2s32 geom)
166 void GUIInventoryMenu::drawList(const ListDrawSpec &s)
167 {
168         video::IVideoDriver* driver = Environment->getVideoDriver();
169
170         InventoryList *ilist = m_inventory->getList(s.listname);
171         
172         core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
173
174         for(s32 i=0; i<s.geom.X*s.geom.Y; i++)
175         {
176                 s32 x = (i%s.geom.X) * spacing.X;
177                 s32 y = (i/s.geom.X) * spacing.Y;
178                 v2s32 p(x,y);
179                 core::rect<s32> rect = imgrect + s.pos + p;
180                 InventoryItem *item = NULL;
181                 if(ilist)
182                         item = ilist->getItem(i);
183
184                 if(m_selected_item != NULL && m_selected_item->listname == s.listname
185                                 && m_selected_item->i == i)
186                 {
187                         driver->draw2DRectangle(video::SColor(255,255,0,0),
188                                         core::rect<s32>(rect.UpperLeftCorner - v2s32(2,2),
189                                                         rect.LowerRightCorner + v2s32(2,2)),
190                                                         &AbsoluteClippingRect);
191                 }
192                 drawInventoryItem(Environment, item,
193                                 rect, &AbsoluteClippingRect);
194         }
195 }
196
197 void GUIInventoryMenu::draw()
198 {
199         if(!IsVisible)
200                 return;
201                 
202         gui::IGUISkin* skin = Environment->getSkin();
203         if (!skin)
204                 return;
205         video::IVideoDriver* driver = Environment->getVideoDriver();
206         
207         video::SColor bgcolor(140,0,0,0);
208         driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
209
210         /*
211                 Draw items
212         */
213         
214         for(u32 i=0; i<m_draw_positions.size(); i++)
215         {
216                 ListDrawSpec &s = m_draw_positions[i];
217                 drawList(s);
218         }
219
220         /*
221                 Call base class
222         */
223         gui::IGUIElement::draw();
224 }
225
226 bool GUIInventoryMenu::OnEvent(const SEvent& event)
227 {
228         if(event.EventType==EET_KEY_INPUT_EVENT)
229         {
230                 if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
231                 {
232                         setVisible(false);
233                         return true;
234                 }
235                 if(event.KeyInput.Key==KEY_KEY_I && event.KeyInput.PressedDown)
236                 {
237                         setVisible(false);
238                         return true;
239                 }
240         }
241         if(event.EventType==EET_MOUSE_INPUT_EVENT)
242         {
243                 if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
244                 {
245                         v2s32 p(event.MouseInput.X, event.MouseInput.Y);
246                         //dstream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
247                         ItemSpec s = getItemAtPos(p);
248                         if(s.isValid())
249                         {
250                                 //dstream<<"Mouse down on "<<s.listname<<" "<<s.i<<std::endl;
251                                 if(m_selected_item)
252                                 {
253                                         InventoryList *list_from =
254                                                         m_inventory->getList(m_selected_item->listname);
255                                         InventoryList *list_to =
256                                                         m_inventory->getList(s.listname);
257                                         if(list_from && list_to
258                                                         && list_from->getItem(m_selected_item->i) != NULL)
259                                         {
260                                                 dstream<<"Queueing IACTION_MOVE"<<std::endl;
261                                                 IMoveAction *a =
262                                                         new IMoveAction();
263                                                 a->count = 1;
264                                                 a->from_name = m_selected_item->listname;
265                                                 a->from_i = m_selected_item->i;
266                                                 a->to_name = s.listname;
267                                                 a->to_i = s.i;
268                                                 m_actions.push_back(a);
269                                         }
270                                         delete m_selected_item;
271                                         m_selected_item = NULL;
272                                 }
273                                 else
274                                 {
275                                         /*
276                                                 Select if non-NULL
277                                         */
278                                         InventoryList *list = m_inventory->getList(s.listname);
279                                         if(list->getItem(s.i) != NULL)
280                                         {
281                                                 m_selected_item = new ItemSpec(s);
282                                         }
283                                 }
284                         }
285                         else
286                         {
287                                 if(m_selected_item)
288                                 {
289                                         delete m_selected_item;
290                                         m_selected_item = NULL;
291                                 }
292                         }
293                 }
294         }
295         if(event.EventType==EET_GUI_EVENT)
296         {
297                 if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
298                                 && isVisible())
299                 {
300                         if(!canTakeFocus(event.GUIEvent.Element))
301                         {
302                                 dstream<<"GUIInventoryMenu: Not allowing focus change."
303                                                 <<std::endl;
304                                 // Returning true disables focus change
305                                 return true;
306                         }
307                 }
308                 if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
309                 {
310                         /*switch(event.GUIEvent.Caller->getID())
311                         {
312                         case 256: // continue
313                                 setVisible(false);
314                                 break;
315                         case 257: // exit
316                                 dev->closeDevice();
317                                 break;
318                         }*/
319                 }
320         }
321
322         return Parent ? Parent->OnEvent(event) : false;
323 }
324
325 InventoryAction* GUIInventoryMenu::getNextAction()
326 {
327         if(m_actions.size() == 0)
328                 return NULL;
329         return m_actions.pop_front();
330 }
331
332