ya2 · news · projects · code · about

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