1 from dataclasses
import dataclass
2 from panda3d
.core
import TextNode
3 from direct
.gui
.OnscreenText
import OnscreenText
4 from direct
.gui
.DirectGui
import DirectButton
, DirectOptionMenu
, DirectSlider
, DirectCheckButton
5 from direct
.gui
.DirectGuiGlobals
import FLAT
6 from ya2
.utils
.audio
import AudioTools
7 from ya2
.utils
.gfx
import DirectGuiMixin
, GfxTools
8 from ya2
.utils
.gui
.gui
import GuiTools
11 class DirectOptionMenuTestable(DirectOptionMenu
):
13 def __init__(self
, parent
=None, **kw
):
14 DirectOptionMenu
.__init
__(self
, parent
, **kw
)
15 self
.initialiseoptions(DirectOptionMenuTestable
)
17 def showPopupMenu(self
, event
=None):
18 #super().showPopupMenu(event) # it does not work with mixins
19 DirectOptionMenu
.showPopupMenu(self
, event
)
20 self
._show
_cb
([self
.component(c
) for c
in self
.components()])
31 text_scale
: ... = None
35 def to_p3d_args(self
):
38 d
['pos'] = self
.pos
or (0, 1, 0)
39 d
['scale'] = self
.scale
or .12
40 d
['font'] = self
.font
or GuiTools
.load_font('assets/fonts/Hanken-Book.ttf')
41 d
['fg'] = self
.color
or (.9, .9, .9, 1)
46 class ButtonArgs(BaseArgs
):
48 command_args
: ... = None
50 text_color
: ... = None
52 rollover_sound
: ... = None
53 click_sound
: ... = None
55 def to_p3d_args(self
):
56 d
= super().to_p3d_args()
57 d
['frameSize'] = self
.size
or (-4.8, 4.8, -.6, 1.2)
58 d
['command'] = self
.command
59 d
['extraArgs'] = self
.command_args
or []
60 d
['text_fg'] = self
.text_color
or d
.pop('fg')
61 if 'fg' in d
: del d
['fg']
62 d
['text_font'] = self
.font
or d
.pop('font')
63 d
['frameColor'] = self
.color
or (.4, .4, .4, .14)
64 d
['relief'] = self
.relief
or FLAT
65 d
['rolloverSound'] = self
.rollover_sound
or AudioTools
.load_sfx('assets/audio/sfx/rollover.ogg')
66 d
['clickSound'] = self
.click_sound
or AudioTools
.load_sfx('assets/audio/sfx/click.ogg')
67 d
['pos'] = (self
.pos
[0], 1, self
.pos
[1]) if len(self
.pos
) == 2 else self
.pos
68 d
['text_wordwrap'] = self
.wordwrap
69 d
['frameTexture'] = self
.texture
70 d
['text_scale'] = self
.text_scale
or 1
73 def __build_gui_args(self
):
76 'text_font': GuiTools
.load_font('assets/fonts/Hanken-Book.ttf'),
77 'text_fg': (.9, .9, .9, 1),
79 'frameColor': (.4, .4, .4, .14),
80 'rolloverSound': AudioTools
.load_sfx('assets/audio/sfx/rollover.ogg'),
81 'clickSound': AudioTools
.load_sfx('assets/audio/sfx/click.ogg')}
82 button
= {'size': (-4.8, 4.8, -.6, 1.2)} | base
87 class SliderArgs(ButtonArgs
):
92 def to_p3d_args(self
):
93 d
= super().to_p3d_args()
94 d
['range'] = self
.range or (0, 1)
95 d
['thumb_frameColor'] = (.4, .4, .4, .4)
96 d
['thumb_scale'] = 1.6
97 d
['thumb_relief'] = d
['relief']
98 d
['scale'] = self
.scale
or .4
99 d
['value'] = self
.value
or 0
100 del d
['rolloverSound']
107 class OptionMenuArgs(ButtonArgs
):
109 initial_item
: ... = None
110 item_color
: ... = None
111 popup_color
: ... = None
112 item_relief
: ... = None
113 item_text_font
: ... = None
114 item_text_fg
: ... = None
115 highlight_color
: ... = None
116 text_align
: ... = None
118 def to_p3d_args(self
):
119 d
= super().to_p3d_args()
120 d
['items'] = self
.items
121 d
['initialitem'] = self
.initial_item
122 d
['item_frameColor'] = d
['frameColor']
123 d
['popupMarker_frameColor'] = d
['frameColor']
124 d
['popupMarker_relief'] = d
['relief']
125 d
['item_relief'] = d
['relief']
126 d
['item_text_font'] = d
['text_font']
127 d
['item_text_fg'] = d
['text_fg']
128 d
['textMayChange'] = 1
130 h
= (h
[0] + .2, h
[1] + .2, h
[2] + .2, h
[3] + .2)
131 d
['highlightColor'] = self
.highlight_color
or h
132 d
['text_align'] = TextNode
.A_center
133 d
['frameSize'] = (f
:=d
['frameSize'])[0], f
[1] - .56, f
[2], f
[3]
138 class CheckButtonArgs(ButtonArgs
):
141 def to_p3d_args(self
):
142 d
= super().to_p3d_args()
144 h
= (h
[0] + .2, h
[1] + .2, h
[2] + .2, h
[3] + .2)
145 d
['indicator_frameColor'] = h
146 d
['indicator_relief'] = d
['relief']
147 d
['indicatorValue'] = self
.value
or 0
152 class TextArgs(BaseArgs
):
155 def to_p3d_args(self
):
156 d
= super().to_p3d_args()
158 a
= {'left': TextNode
.A_left
,
159 'right': TextNode
.A_right
,
160 'center': TextNode
.A_center
}[self
.align
]
167 def __init__(self
, page_info
):
169 self
._page
_info
= page_info
170 for k
in list(self
._page
_info
.test_positions
.keys()):
171 del self
._page
_info
.test_positions
[k
]
172 self
._build
_widgets
()
174 def _add_text(self
, text_info
):
176 **text_info
.to_p3d_args())
177 self
.__widgets
+= [t
]
180 def _add_button(self
, button_args
, vertically_centered
=False):
181 b
= DirectButton(**button_args
.to_p3d_args())
182 b
.__class
__ = type('DirectButtonMixed', (DirectButton
, DirectGuiMixin
), {})
183 self
._page
_info
.test_positions
[button_args
.id] = b
.pos_pixel()
184 self
.__widgets
+= [b
]
185 if vertically_centered
:
187 tnode
= b
.component('text%s' % j
).textNode
188 height
= - tnode
.getLineHeight() / 2
189 height
+= (tnode
.get_height() - tnode
.get_line_height()) / 2
190 b
.component('text%s' % j
).set_pos(0, 0, height
)
193 def _add_check_button(self
, button_args
):
194 b
= DirectCheckButton(**button_args
.to_p3d_args())
195 b
.__class
__ = type('DirectCheckButtonMixed', (DirectCheckButton
, DirectGuiMixin
), {})
196 self
.__widgets
+= [b
]
197 self
._page
_info
.test_positions
[button_args
.id] = b
.pos_pixel()
200 def _add_option_menu(self
, option_args
, cb
):
201 o
= DirectOptionMenuTestable(**option_args
.to_p3d_args())
202 o
.__class
__ = type('DirectOptionMenuMixed', (DirectOptionMenu
, DirectGuiMixin
), {})
204 o
.popupMenu
['frameColor'] = option_args
.to_p3d_args()['frameColor']
205 o
.popupMenu
['relief'] = option_args
.to_p3d_args()['relief']
206 self
.__widgets
+= [o
]
207 self
._page
_info
.test_positions
[option_args
.id] = o
.pos_pixel()
210 def _add_slider(self
, slider_args
):
211 s
= DirectSlider(**slider_args
.to_p3d_args())
212 s
.__class
__ = type('DirectSliderMixed', (DirectSlider
, DirectGuiMixin
), {})
213 self
._page
_info
.test_positions
['volume'] = s
.pos_pixel()
214 np_left
= GfxTools
.build_empty_node('left_slider')
215 np_left
.set_pos(s
.get_net_transform().get_pos())
216 np_left
.set_x(np_left
.get_x() - s
.get_scale()[0])
217 lpos
= np_left
.pos_as_widget() # try with pos2d_pixel and remove pos_as_widget if ok
218 self
.__widgets
+= [s
]
219 self
._page
_info
.test_positions
['volume_0'] = lpos
222 def _set_page(self
, page_name
):
223 self
._page
_info
.set_page(page_name
)
227 self
._set
_page
('main')
229 def _rearrange_buttons_width(self
):
231 for w
in self
.__widgets
:
232 t
= w
.component('text0')
233 ul
= t
.textNode
.get_upper_left_3d()
234 lr
= t
.textNode
.get_lower_right_3d()
235 max_width
= max(lr
[0] - ul
[0], max_width
)
236 for w
in self
.__widgets
:
237 m_w
= max_width
/ 2 + .8
238 w
['frameSize'] = -m_w
, m_w
, w
['frameSize'][2], w
['frameSize'][3]
241 for w
in self
.__widgets
: w
.destroy()
242 self
._page
_info
= None