1 from inspect
import getmro
2 from panda3d
.core
import TextNode
, Texture
3 from direct
.gui
.DirectGuiGlobals
import FLAT
, ENTER
, EXIT
, DISABLED
, NORMAL
, \
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
16 from ya2
.observer
import Subject
17 # from ya2.lib.ivals import Seq, Wait, PosIval, Func
23 from ya2
.lib
.gui
import Frame
, Slider
, Btn
, Label
, OptionMenu
, \
24 CheckBtn
, Entry
, Img
, Text
, ScrolledFrame
25 from ya2
.lib
.p3d
.widget
import FrameMixin
, SliderMixin
, BtnMixin
, \
26 OptionMenuMixin
, CheckBtnMixin
, EntryMixin
, ImgMixin
, \
28 self
.__class
__ = self
.__class
__ # for pylint
31 ScrolledFrameMixin
: [ScrolledFrame
],
32 SliderMixin
: [Slider
],
33 BtnMixin
: [Btn
, Label
],
34 OptionMenuMixin
: [OptionMenu
],
35 CheckBtnMixin
: [CheckBtn
],
37 ImgMixin
: [Img
, Text
]}
38 for libwdg
, wdgcls
in libwdg2wdg
.items():
39 if any(cls
in getmro(self
.__class
__) for cls
in wdgcls
):
41 clsname
= self
.__class
__.__name
__ + 'Widget'
42 self
.__class
__ = type(clsname
, (self
.__class
__, par_cls
), {})
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
))
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
))
53 Wait(abs(pos
.y
- 1) / 4),
54 PosIval(self
.get_np(), .5, start_pos
)
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
)
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
)
68 if hasattr(self
, 'bind_transl'): self
.wdg
['text'] = self
.bind_transl
71 class P3dImg(CommonBase
):
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)
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
)
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
)
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]))
102 def set_pos(self
, pos
): return self
.img
.set_pos(pos
[0], 1, pos
[1])
104 def get_pos(self
, pos
=None): return self
.img
.get_pos(*[pos
] if pos
else [])
107 def parent(self
): return self
.img
.get_parent()
110 def hidden(self
): return self
.img
.is_hidden()
112 def set_transparent(self
): return self
.img
.set_transparency(True)
114 def destroy(self
): self
.img
= self
.img
.destroy()
117 # class P3dBase(CommonBase):
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)
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()
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
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
140 # def get_pos(self, pos=None):
141 # return self.wdg.get_pos(*[pos] if pos else [])
143 # def __setitem__(self, key, value): self.wdg[key] = value
145 # def __getitem__(self, key): return self.wdg[key]
147 # def get_np(self): return self.wdg
150 # def hidden(self): return self.wdg.is_hidden()
152 # def destroy(self): self.wdg.destroy()
155 # class P3dAbs(P3dBase):
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)
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)
172 # def is_enabled(self): return self.wdg['state'] != DISABLED
175 # class P3dBtn(P3dAbs):
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))
198 # def _on_enter(self, pos): pass # pos comes from mouse
200 # def _on_exit(self, pos): pass # pos comes from mouse
202 # # we add these with the mixins
203 # # def enable(self): self['state'] = NORMAL
205 # # def disable(self): self['state'] = DISABLED
208 # class P3dSlider(P3dAbs):
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)
221 # class P3dCheckBtn(P3dAbs):
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,
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,
235 # P3dAbs.__init__(self, tra_src, tra_tra)
238 # class P3dOptionMenu(P3dAbs):
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)
262 # def set(self, idx, f_cmd=1): return self.wdg.set(idx, f_cmd)
265 # def curr_val(self): return self.wdg.get()
268 # def curr_idx(self): return self.wdg.selectedIndex
271 # class P3dEntry(P3dAbs, DirectObject, Subject):
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,
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,
295 # P3dAbs.__init__(self, tra_src, tra_tra)
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)
301 # def set(self, txt): return self.wdg.set(txt)
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')
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')
314 # if self.wdg['focus'] == ENTRY_FOCUS_STATE: self.on_tab_cb()
317 # def focused(self): return self.__focused
320 # def text(self): return self.wdg.get()
322 # def enter_text(self, txt):
323 # return self.wdg.enterText(txt)
325 # def enable(self): self['state'] = NORMAL
327 # def disable(self): self['state'] = DISABLED
330 # self.ignore('tab-up')
331 # self.on_tab_cb = None
332 # Subject.destroy(self)
333 # P3dAbs.destroy(self)
336 # class P3dLabel(P3dAbs):
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)
349 # def set_bin(self, bin_name, priority): return self.wdg.set_bin(bin_name, priority)
351 # def set_x(self, x): return self.wdg.set_x(x)
353 # def set_alpha_scale(self, alpha): return self.wdg.set_alpha_scale(alpha)
356 # class P3dTxt(P3dBase):
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,
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)
374 # def set_r(self, r): return self.wdg.set_r(r)
377 # class P3dFrame(P3dAbs):
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()
387 # class P3dScrolledFrame(P3dAbs):
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]),
405 # def canvas(self): return self.wdg.getCanvas()