3eac6f56e861e396c30e6d408ca12a16814cfe27
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
, LPoint3f
7 from direct
.gui
.OnscreenImage
import OnscreenImage
8 from direct
.gui
.DirectGui
import DirectButton
, DirectEntry
, DirectOptionMenu
, OkDialog
, DirectFrame
9 from direct
.gui
.DirectGuiGlobals
import FLAT
, NORMAL
10 from direct
.gui
.OnscreenText
import OnscreenText
11 from direct
.showbase
.DirectObject
import DirectObject
12 from ya2
.utils
.gfx
import DirectGuiMixin
13 from pmachines
.items
.item
import Item
, ItemStrategy
14 from pmachines
.editor
.augmented_frame
import AugmentedDirectFrame
15 from ya2
.utils
.gui
.base_page
import DirectOptionMenuTestable
18 class StartItems(DirectObject
):
20 def __init__(self
, json_items
, pos_mgr
, item_classes
, strategy_items
):
22 self
.__items
= json_items
23 self
.__json
= self
.__items
[0]
24 self
.__pos
_mgr
= pos_mgr
25 self
._font
= base
.loader
.load_font(
26 'assets/fonts/Hanken-Book.ttf')
28 self
._font
.set_pixels_per_unit(60)
29 self
._font
.set_minfilter(Texture
.FTLinearMipmapLinear
)
30 self
._font
.set_outline((0, 0, 0, 1), .8, .2)
33 'text_font': self
._font
,
34 'text_fg': (.9, .9, .9, 1),
36 'frameColor': (.4, .4, .4, .14),
37 'rolloverSound': loader
.load_sfx(
38 'assets/audio/sfx/rollover.ogg'),
39 'clickSound': loader
.load_sfx(
40 'assets/audio/sfx/click.ogg')}
41 tooltip_args
= self
._common
['text_font'], self
._common
['scale'], self
._common
['text_fg']
43 self
._frm
= AugmentedDirectFrame(frameColor
=(.4, .4, .4, .06),
44 frameSize
=(0, w
, -h
, 0),
45 parent
=base
.a2dTopLeft
,
47 delta_drag
=LPoint3f(w
, 0, -h
),
48 collapse_pos
=(w
- .06, 1, -h
+ .06),
52 # item_modules = glob('pmachines/items/*.py')
53 # item_modules = [basename(i)[:-3] for i in item_modules]
55 # for item_module in item_modules:
56 # mod_name = 'pmachines.items.' + item_module
57 # for member in import_module(mod_name).__dict__.values():
58 # if isclass(member) and issubclass(member, Item) and \
60 # new_items = list(set(new_items + [member.__name__]))
61 item_names
= [i
.__name
__ for i
in item_classes
]
62 t
, item_class_entry
= self
.__add
_row
_option
(_('class'), '', item_names
, self
.on_edit_class
, _('class of the item'))
64 def item_class_set(comps
):
65 class_labels
= [f
'start_class_{i.lower()}' for i
in item_names
]
66 for i
in class_labels
:
67 if i
in self
.__pos
_mgr
:
69 for l
, b
in zip(class_labels
, comps
):
70 b
.__class
__ = type('DirectFrameMixed', (DirectFrame
, DirectGuiMixin
), {})
72 self
.__pos
_mgr
[l
] = (p
[0] + 5, p
[1])
73 item_class_entry
._show
_cb
= item_class_set
74 self
.__pos
_mgr
['editor_start_class'] = item_class_entry
.pos_pixel()
76 t
, count_entry
= self
.__add
_row
('count', _('count'), '', self
.on_edit_count
, _('number of the items'))
77 t
, scale_entry
= self
.__add
_row
('scale', _('scale'), '', self
.on_edit_scale
, _('scale (e.g. 1.2)'))
78 t
, mass_entry
= self
.__add
_row
('mass', _('mass'), '', self
.on_edit_mass
, _('mass (default 1)'))
79 t
, restitution_entry
= self
.__add
_row
('restitution', _('restitution'), '', self
.on_edit_restitution
, _('restitution (default 0.5)'))
80 t
, friction_entry
= self
.__add
_row
('friction', _('friction'), '', self
.on_edit_friction
, _('friction (default 0.5)'))
81 t
, id_entry
= self
.__add
_row
('id', _('id'), '', self
.on_edit_id
, _('id'))
82 # strategy_items = ['']
83 # for item_module in item_modules:
84 # mod_name = 'pmachines.items.' + item_module
85 # for member in import_module(mod_name).__dict__.values():
86 # if isclass(member) and issubclass(member, ItemStrategy) and \
87 # member != ItemStrategy:
88 # strategy_items = list(set(strategy_items + [member.__name__]))
89 strategy_names
= [s
.__name
__ for s
in strategy_items
]
90 t
, strategy_entry
= self
.__add
_row
_option
(_('strategy'), '', strategy_names
, self
.on_edit_strategy
, _('the strategy of the item'))
92 def strategy_set(comps
):
93 strategy_labels
= [f
'start_strategy_{i.lower()}' for i
in strategy_names
]
94 for i
in strategy_labels
:
95 if i
in self
.__pos
_mgr
:
97 for l
, b
in zip(strategy_labels
, comps
):
98 b
.__class
__ = type('DirectFrameMixed', (DirectFrame
, DirectGuiMixin
), {})
100 self
.__pos
_mgr
[l
] = (p
[0] + 5, p
[1])
101 strategy_entry
._show
_cb
= strategy_set
102 p
= strategy_entry
.pos_pixel()
103 self
.__pos
_mgr
['editor_start_strategy'] = (p
[0] + 5, p
[1])
105 t
, strategy_args_entry
= self
.__add
_row
('strategy_args', _('strategy_args'), '', self
.on_edit_strategy_args
, _('the arguments of the strategy'))
106 fields
= ['scale', 'mass', 'restitution', 'friction', 'id', 'strategy', 'strategy_args', 'item_class', 'count']
107 Entries
= namedtuple('Entries', fields
)
108 self
.__entries
= Entries(scale_entry
, mass_entry
, restitution_entry
, friction_entry
, id_entry
, strategy_entry
, strategy_args_entry
, item_class_entry
, count_entry
)
109 self
.__set
(self
.__json
)
110 def load_images_btn(path
, col
):
113 (.6, .6, .6, 1), # ready
114 (1, 1, 1, 1), # press
115 (.8, .8, .8, 1), # rollover
121 (.4, .1, .1, .4)]}[col
]
122 return [self
.__load
_img
_btn
(path
, col
) for col
in colors
]
123 fcols
= (.4, .4, .4, .14), (.3, .3, .3, .05)
125 image
=load_images_btn('exitRight', 'gray'), scale
=.05,
126 pos
=(.54, 1, -h
+ .06),
127 parent
=self
._frm
, command
=self
.destroy
, state
=NORMAL
, relief
=FLAT
,
129 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
130 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
131 b
.__class
__ = type('DirectButtonMixed', (DirectButton
, DirectGuiMixin
), {})
132 pos_mgr
['editor_start_close'] = b
.pos_pixel()
133 b
.set_tooltip(_('Close'), *tooltip_args
)
135 image
=load_images_btn('save', 'gray'), scale
=.05,
136 pos
=(.42, 1, -h
+ .06),
137 parent
=self
._frm
, command
=self
.__save
, state
=NORMAL
, relief
=FLAT
,
139 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
140 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
141 b
.__class
__ = type('DirectButtonMixed', (DirectButton
, DirectGuiMixin
), {})
142 pos_mgr
['editor_start_save'] = b
.pos_pixel()
143 b
.set_tooltip(_('Save'), *tooltip_args
)
145 image
=load_images_btn('trashcan', 'gray'), scale
=.05,
146 pos
=(.3, 1, -h
+ .06),
147 parent
=self
._frm
, command
=self
.__delete
_item
, state
=NORMAL
, relief
=FLAT
,
149 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
150 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
151 b
.__class
__ = type('DirectButtonMixed', (DirectButton
, DirectGuiMixin
), {})
152 pos_mgr
['editor_start_delete'] = b
.pos_pixel()
153 b
.set_tooltip(_('Delete'), *tooltip_args
)
155 image
=load_images_btn('plus', 'gray'), scale
=.05,
156 pos
=(.06, 1, -h
+ .06),
157 parent
=self
._frm
, command
=self
.__new
_item
, state
=NORMAL
, relief
=FLAT
,
159 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
160 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
161 b
.__class
__ = type('DirectButtonMixed', (DirectButton
, DirectGuiMixin
), {})
162 pos_mgr
['editor_start_new'] = b
.pos_pixel()
163 b
.set_tooltip(_('New'), *tooltip_args
)
165 image
=load_images_btn('right', 'gray'), scale
=.05,
166 pos
=(.18, 1, -h
+ .06),
167 parent
=self
._frm
, command
=self
.__next
_item
, state
=NORMAL
, relief
=FLAT
,
169 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
170 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
171 b
.__class
__ = type('DirectButtonMixed', (DirectButton
, DirectGuiMixin
), {})
172 pos_mgr
['editor_start_next'] = b
.pos_pixel()
173 b
.set_tooltip(_('Next'), *tooltip_args
)
175 def __add_row(self
, id_
, label
, text
, callback
, tooltip
):
177 tooltip_args
= self
._common
['text_font'], self
._common
['scale'], self
._common
['text_fg']
180 pos
=(.03, self
.__z
), parent
=self
._frm
,
181 font
=self
._common
['text_font'],
182 scale
=self
._common
['scale'],
183 fg
=self
._common
['text_fg'],
184 wordwrap
=20, align
=TextNode
.ALeft
)
186 scale
=self
._common
['scale'],
187 pos
=(.30, 1, self
.__z
),
188 entryFont
=self
._font
,
191 frameColor
=self
._common
['frameColor'],
194 text_fg
=self
._common
['text_fg'],
196 e
.__class
__ = type('DirectEntryMixed', (DirectEntry
, DirectGuiMixin
), {})
197 e
.set_tooltip(tooltip
, *tooltip_args
)
198 self
.__pos
_mgr
[f
'editor_start_{id_}'] = e
.pos_pixel()
202 def __add_row_option(self
, label
, text
, items
, callback
, tooltip
):
203 tooltip_args
= self
._common
['text_font'], self
._common
['scale'], self
._common
['text_fg']
206 pos
=(.03, self
.__z
), parent
=self
._frm
,
207 font
=self
._common
['text_font'],
208 scale
=self
._common
['scale'],
209 fg
=self
._common
['text_fg'],
210 wordwrap
=20, align
=TextNode
.ALeft
)
211 e
= DirectOptionMenuTestable(
212 scale
=self
._common
['scale'],
214 pos
=(.30, 1, self
.__z
),
221 frameColor
=self
._common
['frameColor'],
222 item_frameColor
=self
._common
['frameColor'],
223 popupMenu_frameColor
=self
._common
['frameColor'],
224 popupMarker_frameColor
=self
._common
['frameColor'],
225 text_font
=self
._font
,
226 text_fg
=self
._common
['text_fg'],
227 highlightColor
=(.9, .9, .9, .9),
228 item_text_font
=self
._font
,
229 item_text_fg
=self
._common
['text_fg'],
230 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
231 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
232 e
.__class
__ = type('DirectOptionMenuMixed', (DirectOptionMenu
, DirectGuiMixin
), {})
233 e
.set_tooltip(tooltip
, *tooltip_args
)
237 def __load_img_btn(self
, path
, col
):
238 img
= OnscreenImage('assets/images/buttons/%s.dds' % path
)
239 img
.set_transparency(True)
244 def on_edit_scale(self
, txt
):
246 self
.__json
['model_scale'] = float(txt
)
248 del self
.__json
['model_scale']
250 def on_edit_mass(self
, txt
):
252 self
.__json
['mass'] = float(txt
)
254 del self
.__json
['mass']
256 def on_edit_restitution(self
, txt
):
258 self
.__json
['restitution'] = float(txt
)
260 del self
.__json
['restitution']
262 def on_edit_friction(self
, txt
):
264 self
.__json
['friction'] = float(txt
)
266 del self
.__json
['friction']
268 def on_edit_id(self
, txt
):
270 self
.__json
['id'] = txt
272 del self
.__json
['id']
274 def on_edit_strategy(self
, txt
):
276 self
.__json
['strategy'] = txt
277 self
.__entries
.strategy_args
.set('')
279 def on_edit_strategy_args(self
, txt
):
281 self
.__json
['strategy_args'] = txt
283 del self
.__json
['strategy_args']
285 def on_edit_class(self
, txt
):
287 self
.__json
['class'] = txt
289 def on_edit_count(self
, txt
):
291 self
.__json
['count'] = int(txt
)
293 del self
.__json
['count']
295 def __new_item(self
):
296 curr_index
= self
.__items
.index(self
.__json
)
298 curr_index
= (curr_index
+ 1) % len(self
.__items
)
299 self
.__items
.insert(curr_index
, self
.__json
)
300 self
.__set
(self
.__json
)
302 pprint
.pprint(self
.__items
)
304 def __next_item(self
):
305 curr_index
= self
.__items
.index(self
.__json
)
306 self
.__json
= self
.__items
[(curr_index
+ 1) % len(self
.__items
)]
307 self
.__set
(self
.__json
)
309 pprint
.pprint(self
.__items
)
311 def __delete_item(self
):
312 curr_index
= self
.__items
.index(self
.__json
)
313 if curr_index
== len(self
.__items
): curr_index
= 0
314 self
.__items
.remove(self
.__json
)
317 self
.__json
= self
.__items
[curr_index
]
318 self
.__set
(self
.__json
)
320 pprint
.pprint(self
.__items
)
322 def __set(self
, json
):
323 if 'model_scale' in json
:
324 self
.__entries
.scale
.set(str(json
['model_scale']))
326 self
.__entries
.scale
.set('')
328 self
.__entries
.mass
.set(str(json
['mass']))
330 self
.__entries
.mass
.set('')
331 if 'restitution' in json
:
332 self
.__entries
.restitution
.set(str(json
['restitution']))
334 self
.__entries
.restitution
.set('')
335 if 'friction' in json
:
336 self
.__entries
.friction
.set(str(json
['friction']))
338 self
.__entries
.friction
.set('')
340 self
.__entries
.id.set(str(json
['id']))
342 self
.__entries
.id.set('')
343 if 'strategy' in json
:
344 self
.__entries
.strategy
.set(str(json
['strategy']))
346 self
.__entries
.strategy
.set('')
347 if 'strategy_args' in json
:
348 self
.__entries
.strategy_args
.set(str(json
['strategy_args']))
350 self
.__entries
.strategy_args
.set('')
352 self
.__entries
.item_class
.set(str(json
['class']))
354 self
.__entries
.item_class
.set('')
356 self
.__entries
.count
.set(str(json
['count']))
358 self
.__entries
.count
.set('')
360 pprint
.pprint(self
.__items
)
363 messenger
.send('editor-start-items-save', [self
.__items
])
365 def __show_error_popup(self
):
366 self
.__dialog
= OkDialog(dialogName
='Strategy args errors',
367 text
=_('There are errors in the strategy args.'),
368 command
=self
.__actually
_close
)
369 self
.__dialog
['frameColor'] = (.4, .4, .4, .14)
370 self
.__dialog
['relief'] = FLAT
371 self
.__dialog
.component('text0')['fg'] = (.9, .9, .9, 1)
372 self
.__dialog
.component('text0')['font'] = self
._font
373 for b
in self
.__dialog
.buttonList
:
374 b
['frameColor'] = (.4, .4, .4, .14)
375 b
.component('text0')['fg'] = (.9, .9, .9, 1)
376 b
.component('text0')['font'] = self
._font
377 b
.component('text1')['fg'] = (.9, .1, .1, 1)
378 b
.component('text1')['font'] = self
._font
379 b
.component('text2')['fg'] = (.9, .9, .1, 1)
380 b
.component('text2')['font'] = self
._font
382 def __actually_close(self
, arg
):
383 self
.__entries
.strategy
.set('')
384 self
.__entries
.strategy_args
.set('')
385 self
.__dialog
.cleanup()
389 messenger
.send('editor-start-items-destroy')