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

Revision 261, 13.6 KB checked in by b0rland_parpg, 10 years ago (diff)

Ticket #78, #80: Patch by superfluid. Moving the hud events and context menu code (and inventory code) from world.py to hud.py

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