ya2 · news · projects · code · about

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