source: trunk/game/scripts/inventory.py @ 300

Revision 270, 13.8 KB checked in by orlandov, 10 years ago (diff)

Fix Issue #78

  • Fully move the inventory display logic from World to Hud.
  • World will pass Hud an inventory model which will be passed to the Hud's Inventory object at creation time.
  • Property svn:eol-style set to native
Line 
1#/usr/bin/python
2
3#   This file is part of PARPG.
4
5#   PARPG 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 3 of the License, or
8#   (at your option) any later version.
9
10#   PARPG 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
16#   along with PARPG.  If not, see <http://www.gnu.org/licenses/>.
17
18import sys, os, fife, fifelog, pychan
19from scripts import drag_drop_data as data_drag
20from pychan.tools import callbackWithArguments as cbwa
21from scripts.items import item_image_dict
22
23class Inventory(object):
24    """Main inventory class"""
25    def __init__(self, engine, items, callbacks):
26        """Initialise the instance.
27           @type engine: fife.Engine
28           @param engine: An instance of the fife engine
29           @type items: dict
30           @param items: A dictionary for every slot that goes '{slot:item, slot:item}'
31                         if a slot is not included in the dict, it is assumed to be empty
32           @type callbacks: dict
33           @param callbacks: a dict of callbacks
34               refreshReadyImages:
35                   Function that will make the ready slots on the HUD
36                   reflect those within the inventory
37               toggleInventoryButton:
38                   Function that will toggle the state of the inventory button
39           @return: None"""
40        pychan.init(engine, debug = True)
41        self.engine = engine
42        self.readyCallback = callbacks['refreshReadyImages']
43        self.toggleInventoryButtonCallback = callbacks['toggleInventoryButton']
44        self.original_cursor_id = self.engine.getCursor().getId()
45        # TODO: remove hard-coded string?
46        self.inventory = pychan.loadXML("gui/inventory.xml")
47        self.inventoryShown = False 
48        self.events_to_map = {}
49        # the images that should be used for the buttons when they are "empty"
50        self.empty_images = {'A1':'gui/inv_images/inv_backpack.png',
51                             'A2':'gui/inv_images/inv_backpack.png',
52                             'A3':'gui/inv_images/inv_backpack.png',
53                             'A4':'gui/inv_images/inv_backpack.png',
54                             'A5':'gui/inv_images/inv_backpack.png',
55                             'B1':'gui/inv_images/inv_backpack.png',
56                             'B2':'gui/inv_images/inv_backpack.png',
57                             'B3':'gui/inv_images/inv_backpack.png',
58                             'B4':'gui/inv_images/inv_backpack.png',
59                             'B5':'gui/inv_images/inv_backpack.png',
60                             'C1':'gui/inv_images/inv_backpack.png',
61                             'C2':'gui/inv_images/inv_backpack.png',
62                             'C3':'gui/inv_images/inv_backpack.png',
63                             'C4':'gui/inv_images/inv_backpack.png',
64                             'C5':'gui/inv_images/inv_backpack.png',
65                             'D1':'gui/inv_images/inv_backpack.png',
66                             'D2':'gui/inv_images/inv_backpack.png',
67                             'D3':'gui/inv_images/inv_backpack.png',
68                             'D4':'gui/inv_images/inv_backpack.png',
69                             'D5':'gui/inv_images/inv_backpack.png',
70                             'Head':'gui/inv_images/inv_head.png',
71                             'LeftHeld':'gui/inv_images/inv_litem.png',
72                             'RightHeld':'gui/inv_images/inv_ritem.png',
73                             'LeftHand':'gui/inv_images/inv_lhand.png',
74                             'RightHand':'gui/inv_images/inv_rhand.png',
75                             'Body':'gui/inv_images/inv_torso.png',
76                             'Belt':'gui/inv_images/inv_belt.png',
77                             'Ready1':'gui/inv_images/inv_belt_pouches.png',
78                             'Ready2':'gui/inv_images/inv_belt_pouches.png',
79                             'Ready3':'gui/inv_images/inv_belt_pouches.png',
80                             'Ready4':'gui/inv_images/inv_belt_pouches.png',
81                             'LeftFoot':'gui/inv_images/inv_lfoot.png',
82                             'RightFoot':'gui/inv_images/inv_rfoot.png'}
83        # every button on the inventory and its category
84        self.buttons = {'A1':'main_inv', 'A2':'main_inv', 'A3':'main_inv',
85                        'A4':'main_inv', 'A5':'main_inv', 'B1':'main_inv',
86                        'B2':'main_inv', 'B3':'main_inv', 'B4':'main_inv',
87                        'B5':'main_inv', 'C1':'main_inv', 'C2':'main_inv',
88                        'C3':'main_inv', 'C4':'main_inv', 'C5':'main_inv',
89                        'D1':'main_inv', 'D2':'main_inv', 'D3':'main_inv',
90                        'D4':'main_inv', 'D5':'main_inv',
91                        'LeftFoot':'foot', 'RightFoot':'foot',
92                        'LeftHand':'hand', 'RightHand':'hand',
93                        'Head':'head', 'Ready1':'ready', 
94                        'Ready2':'ready', 'Ready3':'ready', 
95                        'Ready4':'ready', 'Belt':'belt', 'LeftHeld':'held',
96                        'RightHeld':'held', 'Body':'body'}
97        # all possible categories
98        self.locations = ['ready', 'head', 'foot', 'hand',
99                          'belt', 'held', 'body']
100
101        for key in items:
102            widget = self.inventory.findChild(name=key)
103            item = items[key]
104            image = item_image_dict[item]
105
106            widget.item = item
107            widget.up_image = image
108            widget.down_image = image
109            widget.hover_image = image           
110
111        for button in self.buttons:
112            # make every button's callback be self.dragDrop
113            self.events_to_map[button] = cbwa(self.dragDrop, button)
114            ch = self.inventory.findChild(name = button)
115            # make every slot's item be none if it has not already been set
116            if button not in items:
117                ch.item = ""
118
119        self.events_to_map['close_button'] = self.closeInventoryAndToggle
120        self.inventory.mapEvents(self.events_to_map)   
121        self.resetMouseCursor()
122
123    def closeInventory(self):
124        """Close the inventory.
125           @return: None"""
126        self.inventory.hide()
127
128    def closeInventoryAndToggle(self):
129        """Close the inventory screen.
130           @return: None"""
131        self.closeInventory()
132        self.toggleInventoryButtonCallback()
133        self.inventoryShown = False
134
135    def toggleInventory(self, toggleImage=True):
136        """Pause the game and enter the inventory screen, or close the
137           inventory screen and resume the game.
138           @type toggleImage: bool
139           @param toggleImage:
140               Call toggleInventoryCallback if True. Toggling via a
141               keypress requires that we toggle the Hud inventory image
142               explicitly. Clicking on the Hud inventory button toggles the
143               image implicitly, so we don't change it.
144           @return: None"""
145        if not self.inventoryShown:
146            self.showInventory()
147            self.inventoryShown = True
148        else:
149            self.closeInventory()
150            self.inventoryShown = False
151
152        if toggleImage:
153            self.toggleInventoryButtonCallback()
154
155    def showInventory(self):
156        """Show the inventory.
157           @return: None"""
158        self.inventory.show()
159
160    def setMouseCursor(self, image, dummy_image, type = "native"): 
161        """Set the mouse cursor to an image.
162           @type image: string
163           @param image: The image you want to set the cursor to
164           @type dummy_image: string
165           @param dummy_image: ???
166           @type type: string
167           @param type: ???
168           @return: None"""
169        cursor = self.engine.getCursor()
170        cursor_type = fife.CURSOR_IMAGE
171        img_pool = self.engine.getImagePool()
172        if(type == "target"):
173            target_cursor_id = img_pool.addResourceFromFile(image) 
174            dummy_cursor_id = img_pool.addResourceFromFile(dummy_image)
175            cursor.set(cursor_type,target_dummy_cursor_id)
176            cursor.setDrag(cursor_type,target_cursor_id,-16,-16)
177        else:
178            cursor_type = fife.CURSOR_IMAGE
179            zero_cursor_id = img_pool.addResourceFromFile(image)
180            cursor.set(cursor_type,zero_cursor_id)
181            cursor.setDrag(cursor_type,zero_cursor_id)
182           
183    def resetMouseCursor(self):
184        """Reset cursor to default image.
185           @return: None"""
186        c = self.engine.getCursor()
187        img_pool = self.engine.getImagePool()
188        cursor_type = fife.CURSOR_NATIVE
189        # this is the path to the default image
190        cursor_id = self.original_cursor_id
191        c.setDrag(cursor_type, cursor_id)
192        c.set(cursor_type, cursor_id)
193       
194    def dragDrop(self, obj):
195        """Decide whether to drag or drop the image.
196           @type obj: string
197           @param obj: The name of the object within
198                       the dictionary 'self.buttons'
199           @return: None"""
200        if(data_drag.dragging == True):
201            self.dropObject(obj)
202        elif(data_drag.dragging == False):
203            self.dragObject(obj)
204               
205    def dragObject(self, obj):
206        """Drag the selected object.
207           @type obj: string
208           @param obj: The name of the object within
209                       the dictionary 'self.buttons'
210           @return: None"""
211        # get the widget from the inventory with the name obj
212        drag_widget = self.inventory.findChild(name = obj)
213        # only drag if the widget is not empty
214        if (drag_widget.up_image != self.empty_images[obj]):
215            # get it's type (e.g. main_inv)
216            data_drag.dragged_type = self.buttons[obj]
217            # get the item that the widget is 'storing'
218            data_drag.dragged_item = drag_widget.item
219            # get the up and down images of the widget
220            up_image = drag_widget.up_image
221            down_image = drag_widget.down_image
222            # set the mouse cursor to be the widget's image
223            self.setMouseCursor(up_image.source,down_image.source)
224            data_drag.dragged_image = up_image.source
225            data_drag.dragging = True
226            # after dragging the 'item', set the widgets' images
227            # so that it has it's default 'empty' images
228            drag_widget.up_image=(self.empty_images[obj])
229            drag_widget.down_image=(self.empty_images[obj])
230            drag_widget.hover_image=(self.empty_images[obj])
231            # then set it's item to nothing
232            drag_widget.item = ""
233           
234    def dropObject(self, obj):
235        """Drops the object being dropped
236           @type obj: string
237           @param obj: The name of the object within
238                       the dictionary 'self.buttons'
239           @return: None"""
240        # find the type of the place that the object
241        # is being dropped onto
242        data_drag.dropped_type  =  self.buttons[obj]
243        # if the dragged obj or the place it is being dropped is
244        # in the main inventory, drop the object
245        if((data_drag.dragged_type == 'main_inv') or
246           (data_drag.dropped_type == 'main_inv')):
247            drag_widget = self.inventory.findChild(name = obj)
248            drag_widget.up_image = data_drag.dragged_image
249            drag_widget.hover_image = data_drag.dragged_image
250            drag_widget.down_image = data_drag.dragged_image
251            drag_widget.item = data_drag.dragged_item
252            print 'Item: ' + drag_widget.item
253            data_drag.dragging = False
254            #reset the mouse cursor to the normal cursor
255            self.resetMouseCursor()
256            # if the object was dropped onto a ready slot, then
257            # update the hud
258            if (data_drag.dropped_type == 'ready'):
259                self.readyCallback()
260       
261        # if the dragged object's type is the same as the location to
262        # to drop it at's, and the dragged object's type is in
263        # self.locations, then drop the object
264        elif((data_drag.dragged_type == data_drag.dropped_type) and
265             (data_drag.dragged_type in self.locations)):
266            drag_widget = self.inventory.findChild(name = obj)
267            drag_widget.up_image = data_drag.dragged_image
268            drag_widget.hover_image = data_drag.dragged_image
269            drag_widget.down_image = data_drag.dragged_image
270            drag_widget.item = data_drag.dragged_item
271            print 'Item: ' + drag_widget.item
272            data_drag.dragging = False
273            # reset the mouse cursor
274            self.resetMouseCursor()
275            # if the object was dropped onto a ready slot, then
276            # update the hud
277            if(data_drag.dropped_type == 'ready'):
278                self.readyCallback()
279        # otherwise, we assume that the player is trying to
280        # drop an object onto an incompatible slot
281        else:
282            # reset the mouse cursor
283            self.resetMouseCursor()
284            data_drag.dragging = False
285
286    def getItems(self):
287        """
288        Get the items in the inventory slots. If there is no item in the slot, it is skipped
289       
290        @rtype: dict
291        @return: The items in the inventory
292        """
293        items = {}
294
295        for button in self.buttons:
296            widget = self.inventory.findChild(name=button)
297            if (widget.item != ""):
298                items[button] = widget.item
299
300        return items
301               
302    def getImage(self, name):
303        """Return a current image from the inventory
304           @type name: string
305           @param name: name of image to get
306           @return: None"""
307        return self.inventory.findChild(name=name)
308
Note: See TracBrowser for help on using the repository browser.