ya2 · news · projects · code · about

housekeeping: ya2 module
[pmachines.git] / pmachines / editor / start_items.py
1 from collections import namedtuple
2 from glob import glob
3 from importlib import import_module
4 from os.path import basename
5 from inspect import isclass
6 from panda3d.core import Texture, TextNode
7 from direct.gui.OnscreenImage import OnscreenImage
8 from direct.gui.DirectGui import DirectButton, DirectFrame, DirectEntry, DirectOptionMenu, OkDialog
9 from direct.gui.DirectGuiGlobals import FLAT, NORMAL
10 from direct.gui.OnscreenText import OnscreenText
11 from direct.showbase.DirectObject import DirectObject
12 from pmachines.items.item import Item, ItemStrategy
13
14
15 class StartItems(DirectObject):
16
17 def __init__(self, json_items):
18 super().__init__()
19 self.__items = json_items
20 self.__json = self.__items[0]
21 self._font = base.loader.load_font(
22 'assets/fonts/Hanken-Book.ttf')
23 self._font.clear()
24 self._font.set_pixels_per_unit(60)
25 self._font.set_minfilter(Texture.FTLinearMipmapLinear)
26 self._font.set_outline((0, 0, 0, 1), .8, .2)
27 self._common = {
28 'scale': .046,
29 'text_font': self._font,
30 'text_fg': (.9, .9, .9, 1),
31 'relief': FLAT,
32 'frameColor': (.4, .4, .4, .14),
33 'rolloverSound': loader.load_sfx(
34 'assets/audio/sfx/rollover.ogg'),
35 'clickSound': loader.load_sfx(
36 'assets/audio/sfx/click.ogg')}
37 w, h = .8, 1.04
38 self._frm = DirectFrame(frameColor=(.4, .4, .4, .06),
39 frameSize=(0, w, -h, 0),
40 parent=base.a2dTopRight,
41 pos=(-w, 0, 0))
42 self.__z = -.08
43 item_modules = glob('pmachines/items/*.py')
44 item_modules = [basename(i)[:-3] for i in item_modules]
45 new_items = ['']
46 for item_module in item_modules:
47 mod_name = 'pmachines.items.' + item_module
48 for member in import_module(mod_name).__dict__.values():
49 if isclass(member) and issubclass(member, Item) and \
50 member != Item:
51 new_items = list(set(new_items + [member.__name__]))
52 t, item_class_entry = self.__add_row_option(_('class'), '', new_items, self.on_edit_class)
53 t, count_entry = self.__add_row(_('count'), '', self.on_edit_count)
54 t, scale_entry = self.__add_row(_('scale'), '', self.on_edit_scale)
55 t, mass_entry = self.__add_row(_('mass'), '', self.on_edit_mass)
56 t, restitution_entry = self.__add_row(_('restitution'), '', self.on_edit_restitution)
57 t, friction_entry = self.__add_row(_('friction'), '', self.on_edit_friction)
58 t, id_entry = self.__add_row(_('id'), '', self.on_edit_id)
59 new_items = ['']
60 for item_module in item_modules:
61 mod_name = 'pmachines.items.' + item_module
62 for member in import_module(mod_name).__dict__.values():
63 if isclass(member) and issubclass(member, ItemStrategy) and \
64 member != ItemStrategy:
65 new_items = list(set(new_items + [member.__name__]))
66 t, strategy_entry = self.__add_row_option(_('strategy'), '', new_items, self.on_edit_strategy)
67 t, strategy_args_entry = self.__add_row(_('strategy_args'), '', self.on_edit_strategy_args)
68 fields = ['scale', 'mass', 'restitution', 'friction', 'id', 'strategy', 'strategy_args', 'item_class', 'count']
69 Entries = namedtuple('Entries', fields)
70 self.__entries = Entries(scale_entry, mass_entry, restitution_entry, friction_entry, id_entry, strategy_entry, strategy_args_entry, item_class_entry, count_entry)
71 self.__set(self.__json)
72 def load_images_btn(path, col):
73 colors = {
74 'gray': [
75 (.6, .6, .6, 1), # ready
76 (1, 1, 1, 1), # press
77 (.8, .8, .8, 1), # rollover
78 (.4, .4, .4, .4)],
79 'green': [
80 (.1, .68, .1, 1),
81 (.1, 1, .1, 1),
82 (.1, .84, .1, 1),
83 (.4, .1, .1, .4)]}[col]
84 return [self.__load_img_btn(path, col) for col in colors]
85 fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
86 DirectButton(
87 image=load_images_btn('exitRight', 'gray'), scale=.05,
88 pos=(.54, 1, -h + .06),
89 parent=self._frm, command=self.destroy, state=NORMAL, relief=FLAT,
90 frameColor=fcols[0],
91 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
92 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
93 DirectButton(
94 image=load_images_btn('save', 'gray'), scale=.05,
95 pos=(.42, 1, -h + .06),
96 parent=self._frm, command=self.__save, state=NORMAL, relief=FLAT,
97 frameColor=fcols[0],
98 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
99 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
100 DirectButton(
101 image=load_images_btn('trashcan', 'gray'), scale=.05,
102 pos=(.3, 1, -h + .06),
103 parent=self._frm, command=self.__delete_item, state=NORMAL, relief=FLAT,
104 frameColor=fcols[0],
105 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
106 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
107 DirectButton(
108 image=load_images_btn('plus', 'gray'), scale=.05,
109 pos=(.06, 1, -h + .06),
110 parent=self._frm, command=self.__new_item, state=NORMAL, relief=FLAT,
111 frameColor=fcols[0],
112 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
113 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
114 DirectButton(
115 image=load_images_btn('right', 'gray'), scale=.05,
116 pos=(.18, 1, -h + .06),
117 parent=self._frm, command=self.__next_item, state=NORMAL, relief=FLAT,
118 frameColor=fcols[0],
119 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
120 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
121
122 def __add_row(self, label, text, callback):
123 tw = 10
124 t = OnscreenText(
125 label,
126 pos=(.03, self.__z), parent=self._frm,
127 font=self._common['text_font'],
128 scale=self._common['scale'],
129 fg=self._common['text_fg'],
130 wordwrap=20, align=TextNode.ALeft)
131 e = DirectEntry(
132 scale=self._common['scale'],
133 pos=(.30, 1, self.__z),
134 entryFont=self._font,
135 width=tw,
136 cursorKeys=True,
137 frameColor=self._common['frameColor'],
138 initialText=text,
139 parent=self._frm,
140 text_fg=self._common['text_fg'],
141 command=callback)
142 self.__z -= .1
143 return t, e
144
145 def __add_row_option(self, label, text, items, callback):
146 item_modules = glob('pmachines/items/*.py')
147 item_modules = [basename(i)[:-3] for i in item_modules]
148 t = OnscreenText(
149 label,
150 pos=(.03, self.__z), parent=self._frm,
151 font=self._common['text_font'],
152 scale=self._common['scale'],
153 fg=self._common['text_fg'],
154 wordwrap=20, align=TextNode.ALeft)
155 e = DirectOptionMenu(
156 scale=self._common['scale'],
157 initialitem=text,
158 pos=(.30, 1, self.__z),
159 items=items,
160 parent=self._frm,
161 command=callback,
162 state=NORMAL,
163 relief=FLAT,
164 item_relief=FLAT,
165 frameColor=self._common['frameColor'],
166 item_frameColor=self._common['frameColor'],
167 popupMenu_frameColor=self._common['frameColor'],
168 popupMarker_frameColor=self._common['frameColor'],
169 text_font=self._font,
170 text_fg=self._common['text_fg'],
171 highlightColor=(.9, .9, .9, .9),
172 item_text_font=self._font,
173 item_text_fg=self._common['text_fg'],
174 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
175 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
176 self.__z -= .1
177 return t, e
178
179 def __load_img_btn(self, path, col):
180 img = OnscreenImage('assets/images/buttons/%s.dds' % path)
181 img.set_transparency(True)
182 img.set_color(col)
183 img.detach_node()
184 return img
185
186 def on_edit_scale(self, txt):
187 self.__json['model_scale'] = float(txt)
188
189 def on_edit_mass(self, txt):
190 self.__json['mass'] = float(txt)
191
192 def on_edit_restitution(self, txt):
193 self.__json['restitution'] = float(txt)
194
195 def on_edit_friction(self, txt):
196 self.__json['friction'] = float(txt)
197
198 def on_edit_id(self, txt):
199 self.__json['id'] = txt
200
201 def on_edit_strategy(self, txt):
202 if txt:
203 self.__json['strategy'] = txt
204 self.__entries.strategy_args.set('')
205
206 def on_edit_strategy_args(self, txt):
207 self.__json['strategy_args'] = txt
208
209 def on_edit_class(self, txt):
210 if txt:
211 self.__json['class'] = txt
212
213 def on_edit_count(self, txt):
214 self.__json['count'] = int(txt)
215
216 def __new_item(self):
217 curr_index = self.__items.index(self.__json)
218 self.__json = {}
219 curr_index = (curr_index + 1) % len(self.__items)
220 self.__items.insert(curr_index, self.__json)
221 self.__set(self.__json)
222 import pprint
223 pprint.pprint(self.__items)
224
225 def __next_item(self):
226 curr_index = self.__items.index(self.__json)
227 self.__json = self.__items[(curr_index + 1) % len(self.__items)]
228 self.__set(self.__json)
229 import pprint
230 pprint.pprint(self.__items)
231
232 def __delete_item(self):
233 curr_index = self.__items.index(self.__json)
234 if curr_index == len(self.__items): curr_index = 0
235 self.__items.remove(self.__json)
236 if not self.__items:
237 self.__items = [{}]
238 self.__json = self.__items[curr_index]
239 self.__set(self.__json)
240 import pprint
241 pprint.pprint(self.__items)
242
243 def __set(self, json):
244 if 'model_scale' in json:
245 self.__entries.scale.set(str(json['model_scale']))
246 else:
247 self.__entries.scale.set('')
248 if 'mass' in json:
249 self.__entries.mass.set(str(json['mass']))
250 else:
251 self.__entries.mass.set('')
252 if 'restitution' in json:
253 self.__entries.restitution.set(str(json['restitution']))
254 else:
255 self.__entries.restitution.set('')
256 if 'friction' in json:
257 self.__entries.friction.set(str(json['friction']))
258 else:
259 self.__entries.friction.set('')
260 if 'id' in json:
261 self.__entries.id.set(str(json['id']))
262 else:
263 self.__entries.id.set('')
264 if 'strategy' in json:
265 self.__entries.strategy.set(str(json['strategy']))
266 else:
267 self.__entries.strategy.set('')
268 if 'strategy_args' in json:
269 self.__entries.strategy_args.set(str(json['strategy_args']))
270 else:
271 self.__entries.strategy_args.set('')
272 if 'class' in json:
273 self.__entries.item_class.set(str(json['class']))
274 else:
275 self.__entries.item_class.set('')
276 if 'count' in json:
277 self.__entries.count.set(str(json['count']))
278 else:
279 self.__entries.count.set('')
280 import pprint
281 pprint.pprint(self.__items)
282
283 def __save(self):
284 messenger.send('editor-start-items-save', [self.__items])
285
286 def __show_error_popup(self):
287 self.__dialog = OkDialog(dialogName='Strategy args errors',
288 text=_('There are errors in the strategy args.'),
289 command=self.__actually_close)
290 self.__dialog['frameColor'] = (.4, .4, .4, .14)
291 self.__dialog['relief'] = FLAT
292 self.__dialog.component('text0')['fg'] = (.9, .9, .9, 1)
293 self.__dialog.component('text0')['font'] = self._font
294 for b in self.__dialog.buttonList:
295 b['frameColor'] = (.4, .4, .4, .14)
296 b.component('text0')['fg'] = (.9, .9, .9, 1)
297 b.component('text0')['font'] = self._font
298 b.component('text1')['fg'] = (.9, .1, .1, 1)
299 b.component('text1')['font'] = self._font
300 b.component('text2')['fg'] = (.9, .9, .1, 1)
301 b.component('text2')['font'] = self._font
302
303 def __actually_close(self, arg):
304 self.__entries.strategy.set('')
305 self.__entries.strategy_args.set('')
306 self.__dialog.cleanup()
307
308 def destroy(self):
309 self._frm.destroy()
310 messenger.send('editor-start-items-destroy')