1 from collections
import namedtuple
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
15 class StartItems(DirectObject
):
17 def __init__(self
, json_items
):
19 self
.__items
= json_items
20 self
.__json
= self
.__items
[0]
21 self
._font
= base
.loader
.load_font(
22 'assets/fonts/Hanken-Book.ttf')
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)
29 'text_font': self
._font
,
30 'text_fg': (.9, .9, .9, 1),
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')}
38 self
._frm
= DirectFrame(frameColor
=(.4, .4, .4, .06),
39 frameSize
=(0, w
, -h
, 0),
40 parent
=base
.a2dTopRight
,
43 item_modules
= glob('pmachines/items/*.py')
44 item_modules
= [basename(i
)[:-3] for i
in item_modules
]
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 \
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
)
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
):
75 (.6, .6, .6, 1), # ready
77 (.8, .8, .8, 1), # rollover
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)
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
,
91 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
92 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
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
,
98 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
99 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
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
,
105 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
106 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
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
,
112 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
113 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
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
,
119 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
120 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
122 def __add_row(self
, label
, text
, callback
):
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
)
132 scale
=self
._common
['scale'],
133 pos
=(.30, 1, self
.__z
),
134 entryFont
=self
._font
,
137 frameColor
=self
._common
['frameColor'],
140 text_fg
=self
._common
['text_fg'],
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
]
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'],
158 pos
=(.30, 1, self
.__z
),
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'))
179 def __load_img_btn(self
, path
, col
):
180 img
= OnscreenImage('assets/images/buttons/%s.dds' % path
)
181 img
.set_transparency(True)
186 def on_edit_scale(self
, txt
):
187 self
.__json
['model_scale'] = float(txt
)
189 def on_edit_mass(self
, txt
):
190 self
.__json
['mass'] = float(txt
)
192 def on_edit_restitution(self
, txt
):
193 self
.__json
['restitution'] = float(txt
)
195 def on_edit_friction(self
, txt
):
196 self
.__json
['friction'] = float(txt
)
198 def on_edit_id(self
, txt
):
199 self
.__json
['id'] = txt
201 def on_edit_strategy(self
, txt
):
203 self
.__json
['strategy'] = txt
204 self
.__entries
.strategy_args
.set('')
206 def on_edit_strategy_args(self
, txt
):
207 self
.__json
['strategy_args'] = txt
209 def on_edit_class(self
, txt
):
211 self
.__json
['class'] = txt
213 def on_edit_count(self
, txt
):
214 self
.__json
['count'] = int(txt
)
216 def __new_item(self
):
217 curr_index
= self
.__items
.index(self
.__json
)
219 curr_index
= (curr_index
+ 1) % len(self
.__items
)
220 self
.__items
.insert(curr_index
, self
.__json
)
221 self
.__set
(self
.__json
)
223 pprint
.pprint(self
.__items
)
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
)
230 pprint
.pprint(self
.__items
)
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
)
238 self
.__json
= self
.__items
[curr_index
]
239 self
.__set
(self
.__json
)
241 pprint
.pprint(self
.__items
)
243 def __set(self
, json
):
244 if 'model_scale' in json
:
245 self
.__entries
.scale
.set(str(json
['model_scale']))
247 self
.__entries
.scale
.set('')
249 self
.__entries
.mass
.set(str(json
['mass']))
251 self
.__entries
.mass
.set('')
252 if 'restitution' in json
:
253 self
.__entries
.restitution
.set(str(json
['restitution']))
255 self
.__entries
.restitution
.set('')
256 if 'friction' in json
:
257 self
.__entries
.friction
.set(str(json
['friction']))
259 self
.__entries
.friction
.set('')
261 self
.__entries
.id.set(str(json
['id']))
263 self
.__entries
.id.set('')
264 if 'strategy' in json
:
265 self
.__entries
.strategy
.set(str(json
['strategy']))
267 self
.__entries
.strategy
.set('')
268 if 'strategy_args' in json
:
269 self
.__entries
.strategy_args
.set(str(json
['strategy_args']))
271 self
.__entries
.strategy_args
.set('')
273 self
.__entries
.item_class
.set(str(json
['class']))
275 self
.__entries
.item_class
.set('')
277 self
.__entries
.count
.set(str(json
['count']))
279 self
.__entries
.count
.set('')
281 pprint
.pprint(self
.__items
)
284 messenger
.send('editor-start-items-save', [self
.__items
])
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
303 def __actually_close(self
, arg
):
304 self
.__entries
.strategy
.set('')
305 self
.__entries
.strategy_args
.set('')
306 self
.__dialog
.cleanup()
310 messenger
.send('editor-start-items-destroy')