Mercurial > parpg-source
annotate bGrease/impl/controls.py @ 120:adbcdb900fa9
Modified InventoryGrid to set a name for each slot containing the index.
Added getSlot method to InventoryGrid.
Renamed InventoryGUI class to CharacterGUI.
Added InventoryGUI class which handles the inventory part of the CharacterGUI.
An InventoryGUI instance is now created in CharacterGUI.
author | KarstenBock@gmx.net |
---|---|
date | Wed, 05 Oct 2011 12:59:22 +0200 |
parents | ff3e395abf91 |
children | a6bbb732b27b |
rev | line source |
---|---|
5 | 1 ############################################################################# |
2 # | |
3 # Copyright (c) 2010 by Casey Duncan | |
4 # All Rights Reserved. | |
5 # | |
6 # This software is subject to the provisions of the MIT License | |
7 # A copy of the license should accompany this distribution. | |
8 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
9 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
10 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
11 # | |
12 ############################################################################# | |
13 """Control systems for binding controls to game logic""" | |
14 | |
41
ff3e395abf91
Renamed grease to bGrease (Basic Grease) to get rid of conflicts with an already installed grease.
KarstenBock@gmx.net
parents:
5
diff
changeset
|
15 import bGrease |
5 | 16 from pyglet.window import key |
17 | |
18 class KeyControls(grease.System): | |
19 """System that maps subclass-defined action methods to keys. | |
20 | |
21 Keys may be mapped in the subclass definition using decorators | |
22 defined here as class methods or at runtime using the ``bind_key_*`` | |
23 instance methods. | |
24 | |
25 See :ref:`an example implementation in the tutorial <tut-controls-example>`. | |
26 """ | |
27 MODIFIER_MASK = ~(key.MOD_NUMLOCK | key.MOD_SCROLLLOCK | key.MOD_CAPSLOCK) | |
28 """The MODIFIER_MASK allows you to filter out modifier keys that should be | |
29 ignored by the application. By default, capslock, numlock, and scrolllock | |
30 are ignored. | |
31 """ | |
32 | |
33 world = None | |
34 """:class:`grease.World` object this system is bound to""" | |
35 | |
36 def __init__(self): | |
37 self._key_press_map = {} | |
38 self._key_release_map = {} | |
39 self._key_hold_map = {} | |
40 for name in self.__class__.__dict__: | |
41 member = getattr(self, name) | |
42 if hasattr(member, '_grease_hold_key_binding'): | |
43 for binding in member._grease_hold_key_binding: | |
44 self.bind_key_hold(member, *binding) | |
45 if hasattr(member, '_grease_press_key_binding'): | |
46 for binding in member._grease_press_key_binding: | |
47 self.bind_key_press(member, *binding) | |
48 if hasattr(member, '_grease_release_key_binding'): | |
49 for binding in member._grease_release_key_binding: | |
50 self.bind_key_release(member, *binding) | |
51 self.held_keys = set() | |
52 | |
53 ## decorator methods for binding methods to key input events ## | |
54 | |
55 @classmethod | |
56 def key_hold(cls, symbol, modifiers=0): | |
57 """Decorator to bind a method to be executed where a key is held down""" | |
58 def bind(f): | |
59 if not hasattr(f, '_grease_hold_key_binding'): | |
60 f._grease_hold_key_binding = [] | |
61 f._grease_hold_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK)) | |
62 return f | |
63 return bind | |
64 | |
65 @classmethod | |
66 def key_press(cls, symbol, modifiers=0): | |
67 """Decorator to bind a method to be executed where a key is initially depressed""" | |
68 def bind(f): | |
69 if not hasattr(f, '_grease_press_key_binding'): | |
70 f._grease_press_key_binding = [] | |
71 f._grease_press_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK)) | |
72 return f | |
73 return bind | |
74 | |
75 @classmethod | |
76 def key_release(cls, symbol, modifiers=0): | |
77 """Decorator to bind a method to be executed where a key is released""" | |
78 def bind(f): | |
79 if not hasattr(f, '_grease_release_key_binding'): | |
80 f._grease_release_key_binding = [] | |
81 f._grease_release_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK)) | |
82 return f | |
83 return bind | |
84 | |
85 ## runtime binding methods ## | |
86 | |
87 def bind_key_hold(self, method, key, modifiers=0): | |
88 """Bind a method to a key at runtime to be invoked when the key is | |
89 held down, this replaces any existing key hold binding for this key. | |
90 To unbind the key entirely, pass ``None`` for method. | |
91 """ | |
92 if method is not None: | |
93 self._key_hold_map[key, modifiers & self.MODIFIER_MASK] = method | |
94 else: | |
95 try: | |
96 del self._key_hold_map[key, modifiers & self.MODIFIER_MASK] | |
97 except KeyError: | |
98 pass | |
99 | |
100 def bind_key_press(self, method, key, modifiers=0): | |
101 """Bind a method to a key at runtime to be invoked when the key is initially | |
102 pressed, this replaces any existing key hold binding for this key. To unbind | |
103 the key entirely, pass ``None`` for method. | |
104 """ | |
105 if method is not None: | |
106 self._key_press_map[key, modifiers & self.MODIFIER_MASK] = method | |
107 else: | |
108 try: | |
109 del self._key_press_map[key, modifiers & self.MODIFIER_MASK] | |
110 except KeyError: | |
111 pass | |
112 | |
113 def bind_key_release(self, method, key, modifiers=0): | |
114 """Bind a method to a key at runtime to be invoked when the key is releaseed, | |
115 this replaces any existing key hold binding for this key. To unbind | |
116 the key entirely, pass ``None`` for method. | |
117 """ | |
118 if method is not None: | |
119 self._key_release_map[key, modifiers & self.MODIFIER_MASK] = method | |
120 else: | |
121 try: | |
122 del self._key_release_map[key, modifiers & self.MODIFIER_MASK] | |
123 except KeyError: | |
124 pass | |
125 | |
126 def step(self, dt): | |
127 """invoke held key functions""" | |
128 already_run = set() | |
129 for key in self.held_keys: | |
130 func = self._key_hold_map.get(key) | |
131 if func is not None and func not in already_run: | |
132 already_run.add(func) | |
133 func(dt) | |
134 | |
135 def on_key_press(self, key, modifiers): | |
136 """Handle pyglet key press. Invoke key press methods and | |
137 activate key hold functions | |
138 """ | |
139 key_mod = (key, modifiers & self.MODIFIER_MASK) | |
140 if key_mod in self._key_press_map: | |
141 self._key_press_map[key_mod]() | |
142 self.held_keys.add(key_mod) | |
143 | |
144 def on_key_release(self, key, modifiers): | |
145 """Handle pyglet key release. Invoke key release methods and | |
146 deactivate key hold functions | |
147 """ | |
148 key_mod = (key, modifiers & self.MODIFIER_MASK) | |
149 if key_mod in self._key_release_map: | |
150 self._key_release_map[key_mod]() | |
151 self.held_keys.discard(key_mod) | |
152 | |
153 | |
154 if __name__ == '__main__': | |
155 import pyglet | |
156 | |
157 class TestKeyControls(KeyControls): | |
158 | |
159 MODIFIER_MASK = ~(key.MOD_NUMLOCK | key.MOD_SCROLLLOCK | key.MOD_CTRL) | |
160 | |
161 remapped = False | |
162 | |
163 @KeyControls.key_hold(key.UP) | |
164 @KeyControls.key_hold(key.W) | |
165 def up(self, dt): | |
166 print 'UP!' | |
167 | |
168 @KeyControls.key_hold(key.LEFT) | |
169 @KeyControls.key_hold(key.A) | |
170 def left(self, dt): | |
171 print 'LEFT!' | |
172 | |
173 @KeyControls.key_hold(key.RIGHT) | |
174 @KeyControls.key_hold(key.D) | |
175 def right(self, dt): | |
176 print 'RIGHT!' | |
177 | |
178 @KeyControls.key_hold(key.DOWN) | |
179 @KeyControls.key_hold(key.S) | |
180 def down(self, dt): | |
181 print 'DOWN!' | |
182 | |
183 @KeyControls.key_press(key.SPACE) | |
184 def fire(self): | |
185 print 'FIRE!' | |
186 | |
187 @KeyControls.key_press(key.R) | |
188 def remap_keys(self): | |
189 if not self.remapped: | |
190 self.bind_key_hold(None, key.W) | |
191 self.bind_key_hold(None, key.A) | |
192 self.bind_key_hold(None, key.S) | |
193 self.bind_key_hold(None, key.D) | |
194 self.bind_key_hold(self.up, key.I) | |
195 self.bind_key_hold(self.left, key.J) | |
196 self.bind_key_hold(self.right, key.L) | |
197 self.bind_key_hold(self.down, key.K) | |
198 else: | |
199 self.bind_key_hold(None, key.I) | |
200 self.bind_key_hold(None, key.J) | |
201 self.bind_key_hold(None, key.K) | |
202 self.bind_key_hold(None, key.L) | |
203 self.bind_key_hold(self.up, key.W) | |
204 self.bind_key_hold(self.left, key.A) | |
205 self.bind_key_hold(self.right, key.D) | |
206 self.bind_key_hold(self.down, key.S) | |
207 self.remapped = not self.remapped | |
208 | |
209 | |
210 window = pyglet.window.Window() | |
211 window.clear() | |
212 controls = TestKeyControls() | |
213 window.push_handlers(controls) | |
214 pyglet.clock.schedule_interval(controls.step, 0.5) | |
215 pyglet.app.run() | |
216 |