919bcc5246aa3c97935a899d42d7f33dc50b8823
1 from logging
import info
, debug
2 from sys
import platform
, exit
3 from os
import environ
, system
5 from importlib
import import_module
6 from inspect
import isclass
7 from webbrowser
import open_new_tab
8 from panda3d
.core
import Texture
, TextNode
, WindowProperties
, LVector2i
, \
9 TextProperties
, TextPropertiesManager
10 from direct
.gui
.DirectGui
import DirectButton
, DirectCheckButton
, \
11 DirectOptionMenu
, DirectSlider
, DirectCheckButton
12 from direct
.gui
.DirectGuiGlobals
import FLAT
13 from direct
.gui
.OnscreenText
import OnscreenText
14 from lib
.engine
.gui
.cursor
import MouseCursor
15 from game
.scene
import Scene
16 from panda3d
.bullet
import BulletWorld
21 def __init__(self
, fsm
, lang_mgr
, opt_file
, music
, pipeline
, scenes
, fun_test
):
23 self
._lang
_mgr
= lang_mgr
24 self
._opt
_file
= opt_file
26 self
._pipeline
= pipeline
28 self
._fun
_test
= fun_test
29 self
._cursor
= MouseCursor(
30 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
32 self
._font
= base
.loader
.load_font('assets/fonts/Hanken-Book.ttf')
34 self
._font
.set_pixels_per_unit(60)
35 self
._font
.set_minfilter(Texture
.FTLinearMipmapLinear
)
36 self
._font
.set_outline((0, 0, 0, 1), .8, .2)
40 'text_font': self
._font
,
41 'text_fg': (.9, .9, .9, 1),
43 'frameColor': (.4, .4, .4, .14),
44 'rolloverSound': loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
45 'clickSound': loader
.load_sfx('assets/audio/sfx/click.ogg')}
46 self
._common
_btn
= {'frameSize': (-4.8, 4.8, -.6, 1.2)} | self
._common
47 hlc
= self
._common
_btn
['frameColor']
48 hlc
= (hlc
[0] + .2, hlc
[1] + .2, hlc
[2] + .2, hlc
[3] + .2)
50 'item_frameColor': self
._common
_btn
['frameColor'],
51 'popupMarker_frameColor': self
._common
_btn
['frameColor'],
52 'item_relief': self
._common
_btn
['relief'],
53 'item_text_font': self
._common
_btn
['text_font'],
54 'item_text_fg': self
._common
_btn
['text_fg'],
56 'highlightColor': hlc
,
57 'text_align': TextNode
.A_center
,
59 f_s
= self
._common
_opt
['frameSize']
60 self
._common
_opt
['frameSize'] = f_s
[0], f_s
[1] - .56, f_s
[2], f_s
[3]
61 self
._common
_slider
= self
._common |
{
63 'thumb_frameColor': (.4, .4, .4, .4),
66 del self
._common
_slider
['rolloverSound']
67 del self
._common
_slider
['clickSound']
72 self
._widgets
+= [DirectButton(
73 text
=_('Play'), pos
=(0, 1, .6), command
=self
.on_play
,
75 self
._widgets
+= [DirectButton(
76 text
=_('Options'), pos
=(0, 1, .2), command
=self
.on_options
,
78 self
._widgets
+= [DirectButton(
79 text
=_('Credits'), pos
=(0, 1, -.2), command
=self
.on_credits
,
81 self
._widgets
+= [DirectButton(
82 text
=_('Exit'), pos
=(0, 1, -.6), command
=lambda: exit(),
84 self
._rearrange
_width
()
86 def _set_options(self
):
88 self
._lang
_funcs
= [lambda: _('English'), lambda: _('Italian')]
89 items
= [fnc() for fnc
in self
._lang
_funcs
]
93 }[self
._opt
_file
['settings']['language']]
94 btn
= DirectOptionMenu(
95 text
=_('Language'), items
=items
, initialitem
=inititem
,
96 pos
=(0, 1, .8), command
=self
.on_language
, **self
._common
_opt
)
97 btn
.popupMenu
['frameColor'] = self
._common
_btn
['frameColor']
98 btn
.popupMenu
['relief'] = self
._common
_btn
['relief']
99 self
._widgets
+= [btn
]
100 self
._widgets
+= [OnscreenText(
101 _('Volume'), pos
=(-.1, .55), font
=self
._common
['text_font'],
102 scale
=self
._common
['scale'], fg
=self
._common
['text_fg'],
103 align
=TextNode
.A_right
)]
104 self
._widgets
+= [DirectSlider(
106 value
=self
._opt
_file
['settings']['volume'],
107 command
=self
.on_volume
,
108 **self
._common
_slider
)]
109 self
._slider
= self
._widgets
[-1]
110 self
._widgets
+= [DirectCheckButton(
111 text
=_('Fullscreen'), pos
=(0, 1, .3), command
=self
.on_fullscreen
,
112 indicator_frameColor
=self
._common
_opt
['highlightColor'],
113 indicator_relief
=self
._common
_btn
['relief'],
114 indicatorValue
=self
._opt
_file
['settings']['fullscreen'],
116 res
= self
._opt
_file
['settings']['resolution']
117 d_i
= base
.pipe
.get_display_information()
119 return d_i
.get_display_mode_width(idx
), \
120 d_i
.get_display_mode_height(idx
)
122 _res(idx
) for idx
in range(d_i
.get_total_display_modes())]
123 resolutions
= list(set(resolutions
))
124 resolutions
= sorted(resolutions
)
125 resolutions
= [(str(_res
[0]), str(_res
[1])) for _res
in resolutions
]
126 resolutions
= ['x'.join(_res
) for _res
in resolutions
]
128 res
= resolutions
[-1]
129 btn
= DirectOptionMenu(
130 text
=_('Resolution'), items
=resolutions
, initialitem
=res
,
131 pos
=(0, 1, .05), command
=self
.on_resolution
, **self
._common
_opt
)
132 btn
.popupMenu
['frameColor'] = self
._common
_btn
['frameColor']
133 btn
.popupMenu
['relief'] = self
._common
_btn
['relief']
134 self
._widgets
+= [btn
]
135 self
._widgets
+= [DirectCheckButton(
136 text
=_('Antialiasing'), pos
=(0, 1, -.2), command
=self
.on_aa
,
137 indicator_frameColor
=self
._common
_opt
['highlightColor'],
138 indicator_relief
=self
._common
_btn
['relief'],
139 indicatorValue
=self
._opt
_file
['settings']['antialiasing'],
141 self
._widgets
+= [DirectCheckButton(
142 text
=_('Shadows'), pos
=(0, 1, -.45), command
=self
.on_shadows
,
143 indicator_frameColor
=self
._common
_opt
['highlightColor'],
144 indicator_relief
=self
._common
_btn
['relief'],
145 indicatorValue
=self
._opt
_file
['settings']['shadows'],
147 self
._widgets
+= [DirectButton(
148 text
=_('Back'), pos
=(0, 1, -.8), command
=self
.on_back
,
151 def _set_credits(self
):
153 tp_scale
= TextProperties()
154 tp_scale
.set_text_scale(.64)
155 TextPropertiesManager
.getGlobalPtr().setProperties('scale', tp_scale
)
156 self
._widgets
+= [OnscreenText(
157 _('Code and gfx\n \1scale\1Flavio Calva\2\n\n\nMusic\n \1scale\1Stefan Grossmann\2'),
158 pos
=(-.9, .55), font
=self
._common
['text_font'],
159 scale
=self
._common
['scale'], fg
=self
._common
['text_fg'],
160 align
=TextNode
.A_left
)]
161 self
._widgets
+= [DirectButton(
162 text
=_('Website'), pos
=(-.6, 1, .29), command
=self
.on_website
,
163 **self
._common
_btn |
{'scale': .08})]
164 self
._widgets
+= [OnscreenText(
165 _('Special thanks to:\n \1scale\1rdb\2\n \1scale\1Luisa Tenuta\2\n \1scale\1Damiana Ercolani\2'),
166 pos
=(.1, .55), font
=self
._common
['text_font'],
167 scale
=self
._common
['scale'], fg
=self
._common
['text_fg'],
168 align
=TextNode
.A_left
)]
169 self
._widgets
+= [DirectButton(
170 text
=_('Back'), pos
=(0, 1, -.8), command
=self
.on_back
,
175 self
._cursor
= MouseCursor(
176 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
179 cmn
= self
._common
_btn
.copy() |
{
180 'frameSize': (-2.4, 2.4, -2.4, 2.4),
181 'frameColor': (1, 1, 1, .8),
183 left
= - (dx
:= .8) * (min(4, len(self
._scenes
)) - 1) / 2
184 for i
, cls
in enumerate(self
._scenes
):
185 top
= .1 if len(self
._scenes
) < 5 else .6
186 row
= 0 if i
< 4 else 1
187 self
._widgets
+= [DirectButton(
188 text
=cls
.name(), pos
=(left
+ dx
* (i
% 4), 1, top
- dx
* row
),
189 command
=self
.start
, extraArgs
=[cls
], text_wordwrap
=6,
190 frameTexture
='assets/images/scenes/%s.dds' % cls
.__name
__,
193 tnode
= self
._widgets
[-1].component('text%s' % j
).textNode
194 height
= - tnode
.getLineHeight() / 2
195 height
+= (tnode
.get_height() - tnode
.get_line_height()) / 2
196 self
._widgets
[-1].component('text%s' % j
).set_pos(0, 0, height
)
197 self
._widgets
+= [DirectButton(
198 text
=_('Back'), pos
=(0, 1, -.8), command
=self
.on_back
,
201 def start(self
, cls
):
202 self
._fsm
.demand('Scene', cls
)
204 def on_options(self
):
206 self
._cursor
= MouseCursor(
207 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
211 def on_credits(self
):
213 self
._cursor
= MouseCursor(
214 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
218 def _rearrange_width(self
):
220 for wdg
in self
._widgets
:
221 t_n
= wdg
.component('text0')
222 u_l
= t_n
.textNode
.get_upper_left_3d()
223 l_r
= t_n
.textNode
.get_lower_right_3d()
224 max_width
= max(l_r
[0] - u_l
[0], max_width
)
225 for wdg
in self
._widgets
:
226 m_w
= max_width
/ 2 + .8
227 wdg
['frameSize'] = -m_w
, m_w
, wdg
['frameSize'][2], wdg
['frameSize'][3]
229 def on_language(self
, arg
):
231 _('English'): 'en_EN',
232 _('Italian'): 'it_IT'}[arg
]
233 self
._lang
_mgr
.set_lang(lang_code
)
234 self
._opt
_file
['settings']['language'] = lang_code
[:2]
235 self
._opt
_file
.store()
239 self
._opt
_file
['settings']['volume'] = self
._slider
['value']
240 self
._music
.set_volume(self
._slider
['value'])
242 def on_fullscreen(self
, arg
):
243 props
= WindowProperties()
244 props
.set_fullscreen(arg
)
245 if not self
._fun
_test
:
246 base
.win
.request_properties(props
)
247 # if we actually switch to fullscreen during the tests then
248 # exwm inside qemu can't restore the correct resolution
249 # i may re-enable this if/when i run the tests onto a
251 self
._opt
_file
['settings']['fullscreen'] = int(arg
)
252 self
._opt
_file
.store()
254 def on_resolution(self
, arg
):
255 props
= WindowProperties()
256 props
.set_size(LVector2i(*[int(_res
) for _res
in arg
.split('x')]))
257 base
.win
.request_properties(props
)
258 self
._opt
_file
['settings']['resolution'] = arg
259 self
._opt
_file
.store()
261 def on_aa(self
, arg
):
262 self
._pipeline
.msaa_samples
= 4 if arg
else 1
263 debug(f
'msaa: {self._pipeline.msaa_samples}')
264 self
._opt
_file
['settings']['antialiasing'] = int(arg
)
265 self
._opt
_file
.store()
267 def on_shadows(self
, arg
):
268 self
._pipeline
.enable_shadows
= int(arg
)
269 debug(f
'shadows: {self._pipeline.enable_shadows}')
270 self
._opt
_file
['settings']['shadows'] = int(arg
)
271 self
._opt
_file
.store()
273 def on_website(self
):
274 if platform
.startswith('linux'):
275 environ
['LD_LIBRARY_PATH'] = ''
276 system('xdg-open https://www.ya2.it')
278 open_new_tab('https://www.ya2.it')
281 self
._opt
_file
.store()
283 self
._cursor
= MouseCursor(
284 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
289 [wdg
.destroy() for wdg
in self
._widgets
]
290 self
._cursor
.destroy()