Commit | Line | Data |
---|---|---|
8ee66edd FC |
1 | from inspect import getmro |
2 | from panda3d.core import TextNode, Texture | |
3 | from direct.gui.DirectGuiGlobals import FLAT, ENTER, EXIT, DISABLED, NORMAL, \ | |
4 | B1PRESS | |
5 | from direct.showbase.DirectObject import DirectObject | |
6 | from direct.gui.DirectButton import DirectButton | |
7 | from direct.gui.DirectCheckButton import DirectCheckButton | |
8 | from direct.gui.DirectOptionMenu import DirectOptionMenu | |
9 | from direct.gui.OnscreenImage import OnscreenImage | |
10 | from direct.gui.DirectSlider import DirectSlider | |
11 | from direct.gui.DirectEntry import DirectEntry, ENTRY_FOCUS_STATE | |
12 | from direct.gui.DirectLabel import DirectLabel | |
13 | from direct.gui.DirectFrame import DirectFrame | |
14 | from direct.gui.OnscreenText import OnscreenText | |
15 | from direct.gui.DirectScrolledFrame import DirectScrolledFrame | |
53ddf3c3 | 16 | from ya2.observer import Subject |
cb700bcc | 17 | # from ya2.lib.ivals import Seq, Wait, PosIval, Func |
8ee66edd FC |
18 | |
19 | ||
20 | class CommonBase: | |
21 | ||
22 | def set_widget(self): | |
53ddf3c3 | 23 | from ya2.lib.gui import Frame, Slider, Btn, Label, OptionMenu, \ |
8ee66edd | 24 | CheckBtn, Entry, Img, Text, ScrolledFrame |
53ddf3c3 | 25 | from ya2.lib.p3d.widget import FrameMixin, SliderMixin, BtnMixin, \ |
8ee66edd FC |
26 | OptionMenuMixin, CheckBtnMixin, EntryMixin, ImgMixin, \ |
27 | ScrolledFrameMixin | |
28 | self.__class__ = self.__class__ # for pylint | |
29 | libwdg2wdg = { | |
30 | FrameMixin: [Frame], | |
31 | ScrolledFrameMixin: [ScrolledFrame], | |
32 | SliderMixin: [Slider], | |
33 | BtnMixin: [Btn, Label], | |
34 | OptionMenuMixin: [OptionMenu], | |
35 | CheckBtnMixin: [CheckBtn], | |
36 | EntryMixin: [Entry], | |
37 | ImgMixin: [Img, Text]} | |
38 | for libwdg, wdgcls in libwdg2wdg.items(): | |
39 | if any(cls in getmro(self.__class__) for cls in wdgcls): | |
40 | par_cls = libwdg | |
41 | clsname = self.__class__.__name__ + 'Widget' | |
42 | self.__class__ = type(clsname, (self.__class__, par_cls), {}) | |
43 | self.init(self) | |
44 | if not hasattr(self, 'bind'): return | |
45 | bind_args = [(ENTER, self.on_wdg_enter), (EXIT, self.on_wdg_exit)] | |
46 | list(map(lambda args: self.bind(*args), bind_args)) | |
47 | ||
48 | def set_enter_transition(self): | |
49 | start_pos = self.get_pos() | |
50 | pos = self.pos - (3.6, 0) | |
51 | self.set_pos((pos.x, 1, pos.y)) | |
52 | Seq( | |
53 | Wait(abs(pos.y - 1) / 4), | |
54 | PosIval(self.get_np(), .5, start_pos) | |
55 | ).start() | |
56 | ||
57 | def set_exit_transition(self, destroy): | |
58 | start_pos = self.get_pos() | |
59 | end_pos = (self.pos.x + 3.6, 1, self.pos.y) | |
60 | seq = Seq( | |
61 | Wait(abs(self.pos.y - 1) / 4), | |
62 | PosIval(self.get_np(), .5, end_pos), | |
63 | Func(self.destroy if destroy else self.hide)) | |
64 | if not destroy: seq += Func(self.set_pos, start_pos) | |
65 | seq.start() | |
66 | ||
67 | def translate(self): | |
68 | if hasattr(self, 'bind_transl'): self.wdg['text'] = self.bind_transl | |
69 | ||
70 | ||
71 | class P3dImg(CommonBase): | |
72 | ||
73 | def __init__(self, filepath, pos=(0, 0), scale=1.0, background=False, | |
74 | foreground=False, parent=None): | |
75 | self.img = OnscreenImage( | |
76 | filepath, pos=(pos[0], 1, pos[1]), scale=scale, parent=parent) | |
77 | if background: self.img.set_bin('background', 10) | |
78 | alpha_formats = [12] # panda3d.core.texture.Frgba | |
79 | if self.img.get_texture().get_format() in alpha_formats: | |
80 | self.img.set_transparency(True) | |
81 | if foreground: self.img.set_bin('gui-popup', 50) | |
82 | ||
83 | def reparent_to(self, node): return self.img.reparent_to(node) | |
84 | def show(self): return self.img.show() | |
85 | def hide(self): return self.img.hide() | |
86 | def set_shader(self, shader): return self.img.set_shader(shader) | |
87 | def set_shader_input(self, name, val): | |
88 | return self.img.set_shader_input(name, val) | |
89 | def set_texture(self, texturestage, texture): | |
90 | return self.img.set_texture(texturestage, texture) | |
91 | ||
92 | def set_exit_transition(self, destroy): | |
93 | start_pos = self.get_pos() | |
94 | end_pos = (self.pos.x + 3.6, 1, self.pos.y) | |
95 | seq = Seq( | |
96 | Wait(abs(self.pos.y - 1) / 4), | |
97 | PosIval(self.get_np(), .5, end_pos), | |
98 | Func(self.destroy if destroy else self.hide)) | |
99 | if not destroy: seq += Func(self.set_pos, (start_pos[0], start_pos[2])) | |
100 | seq.start() | |
101 | ||
102 | def set_pos(self, pos): return self.img.set_pos(pos[0], 1, pos[1]) | |
103 | ||
104 | def get_pos(self, pos=None): return self.img.get_pos(*[pos] if pos else []) | |
105 | ||
106 | @property | |
107 | def parent(self): return self.img.get_parent() | |
108 | ||
109 | @property | |
110 | def hidden(self): return self.img.is_hidden() | |
111 | ||
112 | def set_transparent(self): return self.img.set_transparency(True) | |
113 | ||
114 | def destroy(self): self.img = self.img.destroy() | |
115 | ||
116 | ||
cb700bcc | 117 | # class P3dBase(CommonBase): |
8ee66edd | 118 | |
cb700bcc FC |
119 | # def __init__(self, tra_src=None, tra_tra=None): |
120 | # # self.text_src_tra = None # it breaks the gui | |
121 | # if tra_src and tra_tra: self.bind_tra(tra_src, tra_tra) | |
8ee66edd | 122 | |
cb700bcc FC |
123 | # def set_pos(self, pos): return self.wdg.set_pos(pos) |
124 | # def show(self): return self.wdg.show() | |
125 | # def hide(self): return self.wdg.hide() | |
8ee66edd | 126 | |
cb700bcc FC |
127 | # def bind_tra(self, text_src, text_transl): |
128 | # # text_transl is not used, anyway we need it since we have this kind of | |
129 | # # use: self.bind_transl('example str', _('example str')) | |
130 | # # this allows to change translations on the fly keeping the source | |
131 | # # text for remapping it later | |
132 | # # TODO: try reverse mapping? i.e. retrieve the src string from the | |
133 | # # translated one | |
134 | # self.text_src_tra = text_src | |
135 | # self.text_tra_tra = text_transl | |
136 | # tra = lambda self: _(self.text_tra_tra) | |
137 | # self.__class__.bind_transl = property(tra) | |
138 | # self['text'] = self.bind_transl | |
8ee66edd | 139 | |
cb700bcc FC |
140 | # def get_pos(self, pos=None): |
141 | # return self.wdg.get_pos(*[pos] if pos else []) | |
8ee66edd | 142 | |
cb700bcc | 143 | # def __setitem__(self, key, value): self.wdg[key] = value |
8ee66edd | 144 | |
cb700bcc FC |
145 | # def __getitem__(self, key): return self.wdg[key] |
146 | ||
147 | # def get_np(self): return self.wdg | |
148 | ||
149 | # @property | |
150 | # def hidden(self): return self.wdg.is_hidden() | |
151 | ||
152 | # def destroy(self): self.wdg.destroy() | |
153 | ||
154 | ||
155 | # class P3dAbs(P3dBase): | |
156 | ||
157 | # def get_value(self): return self.wdg.getValue() | |
158 | # def initialiseoptions(self): return self.wdg.initialiseoptions() | |
159 | # def set_z(self, val): return self.wdg.set_z(val) | |
160 | # def set_shader(self, shader): return self.wdg.set_shader(shader) | |
161 | # def set_shader_input(self, name, val): | |
162 | # return self.wdg.set_shader_input(name, val) | |
163 | # def set_transparency(self, val): return self.wdg.set_transparency(val) | |
164 | # def bind(self, evt, mth): return self.wdg.bind(evt, mth) | |
165 | ||
166 | # def attachNewNode(self, gui_itm, sort_order): | |
167 | # # it won't work if we name it attach_node. hopefully this will be | |
168 | # # possible when we'll use decorators in place of mixins | |
169 | # return self.wdg.attachNewNode(gui_itm, sort_order) | |
170 | ||
171 | # @property | |
172 | # def is_enabled(self): return self.wdg['state'] != DISABLED | |
173 | ||
174 | ||
175 | # class P3dBtn(P3dAbs): | |
176 | ||
177 | # def __init__( | |
178 | # self, text='', parent=None, pos=(0, 0), scale=(1, 1), | |
179 | # cmd=None, frame_size=(-1, 1, -1, 1), click_snd=None, | |
180 | # text_fg=(1, 1, 1, 1), frame_col=(1, 1, 1, 1), text_font=None, | |
181 | # over_snd=None, extra_args=None, frame_texture=None, img=None, | |
182 | # tra_src=None, tra_tra=None, text_scale=1.0): | |
183 | # str2par = {'bottomcenter': base.a2dBottomCenter} | |
184 | # parent = str2par.get(parent, parent) | |
185 | # extra_args = extra_args or [] | |
186 | # self.wdg = DirectButton( | |
187 | # text=text, parent=parent, pos=(pos[0], 1, pos[1]), | |
188 | # scale=(scale[0], 1, scale[1]), command=cmd, | |
189 | # frameSize=frame_size, clickSound=click_snd, text_fg=text_fg, | |
190 | # frameColor=frame_col, text_font=text_font, rolloverSound=over_snd, | |
191 | # extraArgs=extra_args, frameTexture=frame_texture, image=img, | |
192 | # text_scale=text_scale) | |
193 | # P3dAbs.__init__(self, tra_src, tra_tra) | |
194 | # self['relief'] = FLAT | |
195 | # args = [(ENTER, self._on_enter), (EXIT, self._on_exit)] | |
196 | # list(map(lambda args: self.bind(*args), args)) | |
197 | ||
198 | # def _on_enter(self, pos): pass # pos comes from mouse | |
199 | ||
200 | # def _on_exit(self, pos): pass # pos comes from mouse | |
201 | ||
202 | # # we add these with the mixins | |
203 | # # def enable(self): self['state'] = NORMAL | |
204 | ||
205 | # # def disable(self): self['state'] = DISABLED | |
206 | ||
207 | ||
208 | # class P3dSlider(P3dAbs): | |
209 | ||
210 | # def __init__( | |
211 | # self, parent=None, pos=(0, 0), scale=1, val=0, | |
212 | # frame_col=(1, 1, 1, 1), thumb_frame_col=(1, 1, 1, 1), | |
213 | # cmd=None, range_=(0, 1), tra_src=None, tra_tra=None): | |
214 | # self.wdg = DirectSlider( | |
215 | # parent=parent, pos=(pos[0], 1, pos[1]), scale=scale, value=val, | |
216 | # frameColor=frame_col, thumb_frameColor=thumb_frame_col, | |
217 | # command=cmd, range=range_) | |
218 | # P3dAbs.__init__(self, tra_src, tra_tra) | |
219 | ||
220 | ||
221 | # class P3dCheckBtn(P3dAbs): | |
222 | ||
223 | # def __init__( | |
224 | # self, pos=(0, 0), text='', indicator_val=False, | |
225 | # indicator_frame_col=(1, 1, 1, 1), frame_col=(1, 1, 1, 1), | |
226 | # scale=(1, 1, 1), click_snd=None, over_snd=None, | |
227 | # text_fg=(1, 1, 1, 1), text_font=None, cmd=None, tra_src=None, | |
228 | # tra_tra=None): | |
229 | # self.wdg = DirectCheckButton( | |
230 | # pos=(pos[0], 1, pos[1]), text=text, indicatorValue=indicator_val, | |
231 | # indicator_frameColor=indicator_frame_col, | |
232 | # frameColor=frame_col, scale=scale, clickSound=click_snd, | |
233 | # rolloverSound=over_snd, text_fg=text_fg, text_font=text_font, | |
234 | # command=cmd) | |
235 | # P3dAbs.__init__(self, tra_src, tra_tra) | |
236 | ||
237 | ||
238 | # class P3dOptionMenu(P3dAbs): | |
239 | ||
240 | # def __init__( | |
241 | # self, text='', items=None, pos=(0, 0), scale=(1, 1, 1), | |
242 | # initialitem='', cmd=None, frame_size=(-1, 1, -1, 1), | |
243 | # click_snd=None, over_snd=None, text_may_change=False, | |
244 | # text_fg=(1, 1, 1, 1), item_frame_col=(1, 1, 1, 1), | |
245 | # frame_col=(1, 1, 1, 1), highlight_col=(1, 1, 1, 1), | |
246 | # text_scale=.05, popup_marker_col=(1, 1, 1, 1), | |
247 | # item_relief=None, item_text_font=None, text_font=None, | |
248 | # tra_src=None, tra_tra=None): | |
249 | # items = items or [] | |
250 | # self.wdg = DirectOptionMenu( | |
251 | # text=text, items=items, pos=(pos[0], 1, pos[1]), scale=scale, | |
252 | # initialitem=initialitem, command=cmd, frameSize=frame_size, | |
253 | # clickSound=click_snd, rolloverSound=over_snd, | |
254 | # textMayChange=text_may_change, text_fg=text_fg, | |
255 | # item_frameColor=item_frame_col, frameColor=frame_col, | |
256 | # highlightColor=highlight_col, text_scale=text_scale, | |
257 | # popupMarker_frameColor=popup_marker_col, | |
258 | # item_relief=item_relief, item_text_font=item_text_font, | |
259 | # text_font=text_font) | |
260 | # P3dAbs.__init__(self, tra_src, tra_tra) | |
261 | ||
262 | # def set(self, idx, f_cmd=1): return self.wdg.set(idx, f_cmd) | |
263 | ||
264 | # @property | |
265 | # def curr_val(self): return self.wdg.get() | |
266 | ||
267 | # @property | |
268 | # def curr_idx(self): return self.wdg.selectedIndex | |
269 | ||
270 | ||
271 | # class P3dEntry(P3dAbs, DirectObject, Subject): | |
272 | ||
273 | # def __init__( | |
274 | # self, scale=.05, pos=(0, 0), entry_font=None, width=12, | |
275 | # frame_col=(1, 1, 1, 1), initial_text='', obscured=False, | |
276 | # cmd=None, focus_in_cmd=None, focus_in_args=None, | |
277 | # focus_out_cmd=None, focus_out_args=None, parent=None, | |
278 | # tra_src=None, tra_tra=None, text_fg=(1, 1, 1, 1), on_tab=None, | |
279 | # on_click=None): | |
280 | # self.__focused = False | |
281 | # self.__focus_in_cmd = focus_in_cmd | |
282 | # self.__focus_out_cmd = focus_out_cmd | |
283 | # DirectObject.__init__(self) | |
284 | # Subject.__init__(self) | |
285 | # focus_in_args = focus_in_args or [] | |
286 | # focus_out_args = focus_out_args or [] | |
287 | # self.wdg = DirectEntry( | |
288 | # scale=scale, pos=(pos[0], 1, pos[1]), entryFont=entry_font, | |
289 | # width=width, frameColor=frame_col, initialText=initial_text, | |
290 | # obscured=obscured, command=cmd, focusInCommand=self._focus_in_cmd, | |
291 | # focusInExtraArgs=focus_in_args, | |
292 | # focusOutCommand=self._focus_out_cmd, | |
293 | # focusOutExtraArgs=focus_out_args, parent=parent, | |
294 | # text_fg=text_fg) | |
295 | # P3dAbs.__init__(self, tra_src, tra_tra) | |
296 | # if on_tab: | |
297 | # self.on_tab_cb = on_tab | |
298 | # self.accept('tab-up', self.on_tab) | |
299 | # if on_click: self.wdg.bind(B1PRESS, on_click) | |
300 | ||
301 | # def set(self, txt): return self.wdg.set(txt) | |
302 | ||
303 | # def _focus_in_cmd(self, *args): | |
304 | # self.__focused = True | |
305 | # if self.__focus_in_cmd: self.__focus_in_cmd(*args) | |
306 | # self.notify('on_entry_enter') | |
307 | ||
308 | # def _focus_out_cmd(self, *args): | |
309 | # self.__focused = False | |
310 | # if self.__focus_out_cmd: self.__focus_out_cmd(*args) | |
311 | # self.notify('on_entry_exit') | |
312 | ||
313 | # def on_tab(self): | |
314 | # if self.wdg['focus'] == ENTRY_FOCUS_STATE: self.on_tab_cb() | |
315 | ||
316 | # @property | |
317 | # def focused(self): return self.__focused | |
318 | ||
319 | # @property | |
320 | # def text(self): return self.wdg.get() | |
321 | ||
322 | # def enter_text(self, txt): | |
323 | # return self.wdg.enterText(txt) | |
324 | ||
325 | # def enable(self): self['state'] = NORMAL | |
326 | ||
327 | # def disable(self): self['state'] = DISABLED | |
328 | ||
329 | # def destroy(self): | |
330 | # self.ignore('tab-up') | |
331 | # self.on_tab_cb = None | |
332 | # Subject.destroy(self) | |
333 | # P3dAbs.destroy(self) | |
334 | ||
335 | ||
336 | # class P3dLabel(P3dAbs): | |
337 | ||
338 | # def __init__( | |
339 | # self, text='', pos=(0, 0), parent=None, text_wordwrap=12, | |
340 | # text_align=None, text_fg=(1, 1, 1, 1), text_font=None, scale=.05, | |
341 | # frame_col=(1, 1, 1, 1), tra_src=None, tra_tra=None, hpr=(0, 0, 0)): | |
342 | # self.wdg = DirectLabel( | |
343 | # text=text, pos=(pos[0], 1, pos[1]), parent=parent, | |
344 | # text_wordwrap=text_wordwrap, text_align=text_align, | |
345 | # text_fg=text_fg, text_font=text_font, scale=scale, | |
346 | # frameColor=frame_col, hpr=hpr) | |
347 | # P3dAbs.__init__(self, tra_src, tra_tra) | |
348 | ||
349 | # def set_bin(self, bin_name, priority): return self.wdg.set_bin(bin_name, priority) | |
350 | ||
351 | # def set_x(self, x): return self.wdg.set_x(x) | |
352 | ||
353 | # def set_alpha_scale(self, alpha): return self.wdg.set_alpha_scale(alpha) | |
354 | ||
355 | ||
356 | # class P3dTxt(P3dBase): | |
357 | ||
358 | # def __init__( | |
359 | # self, txt='', pos=(0, 0), scale=.05, wordwrap=12, parent=None, | |
360 | # fg=(1, 1, 1, 1), font=None, align=None, tra_src=None, | |
361 | # tra_tra=None): | |
362 | # str2par = {'bottomleft': base.a2dBottomLeft, | |
363 | # 'bottomright': base.a2dBottomRight, | |
364 | # 'leftcenter': base.a2dLeftCenter} | |
365 | # str2al = {'left': TextNode.A_left, 'right': TextNode.A_right, | |
366 | # 'center': TextNode.A_center} | |
367 | # if parent and parent in str2par: parent = str2par[parent] | |
368 | # if align: align = str2al[align] | |
369 | # self.wdg = OnscreenText( | |
370 | # text=txt, pos=pos, scale=scale, wordwrap=wordwrap, | |
371 | # parent=parent, fg=fg, font=font, align=align) | |
372 | # P3dBase.__init__(self, tra_src, tra_tra) | |
373 | ||
374 | # def set_r(self, r): return self.wdg.set_r(r) | |
375 | ||
376 | ||
377 | # class P3dFrame(P3dAbs): | |
378 | ||
379 | # def __init__(self, frame_size=(-1, 1, -1, 1), frame_col=(1, 1, 1, 1), | |
380 | # pos=(0, 0), parent=None, texture_coord=False): | |
381 | # P3dAbs.__init__(self) | |
382 | # self.wdg = DirectFrame(frameSize=frame_size, frameColor=frame_col, | |
383 | # pos=(pos[0], 1, pos[1]), parent=parent) | |
384 | # if texture_coord: self.wdg['frameTexture'] = Texture() | |
385 | ||
386 | ||
387 | # class P3dScrolledFrame(P3dAbs): | |
388 | ||
389 | # def __init__( | |
390 | # self, frame_sz=(-1, 1, -1, 1), canvas_sz=(0, 1, 0, 1), | |
391 | # scrollbar_width=.05, frame_col=(1, 1, 1, 1), | |
392 | # pos=(0, 0), parent='topleft'): | |
393 | # P3dAbs.__init__(self) | |
394 | # par2p3d = {'topleft': base.a2dTopLeft} | |
395 | # if parent and parent in par2p3d: parent = par2p3d[parent] | |
396 | # self.wdg = DirectScrolledFrame( | |
397 | # frameSize=frame_sz, | |
398 | # canvasSize=canvas_sz, | |
399 | # scrollBarWidth=scrollbar_width, | |
400 | # frameColor=frame_col, | |
401 | # pos=(pos[0], 1, pos[1]), | |
402 | # parent=parent) | |
8ee66edd | 403 | |
cb700bcc FC |
404 | # @property |
405 | # def canvas(self): return self.wdg.getCanvas() |