5 from importlib
import import_module
6 from inspect
import isclass
7 from sys
import platform
, argv
, exit
8 from logging
import info
, debug
9 from os
.path
import exists
10 from os
import makedirs
11 from panda3d
.core
import Filename
, load_prc_file_data
, AntialiasAttrib
, \
12 Texture
, WindowProperties
, LVector2i
13 from panda3d
.bullet
import BulletWorld
, BulletDebugNode
14 from direct
.showbase
.ShowBase
import ShowBase
15 from direct
.fsm
.FSM
import FSM
16 from game
.music
import MusicMgr
17 from game
.items
.background
import Background
18 from game
.menu
import Menu
19 from game
.scene
import Scene
20 from game
.scenes
.scene_basketball
import SceneBasketBall
21 from game
.scenes
.scene_box
import SceneBox
22 from game
.scenes
.scene_domino_box_basketball
import SceneDominoBoxBasketball
23 from game
.scenes
.scene_domino_box
import SceneDominoBox
24 from game
.scenes
.scene_domino
import SceneDomino
25 from game
.scenes
.scene_teeter_domino_box_basketball
import SceneTeeterDominoBoxBasketball
26 from game
.scenes
.scene_teeter_tooter
import SceneTeeterTooter
27 from lib
.dictfile
import DctFile
28 from lib
.lib
.p3d
.p3d
import LibP3d
29 from lib
.engine
.lang
import LangMgr
34 def __init__(self
, pmachines
):
35 super().__init
__('Main FSM')
36 self
._pmachines
= pmachines
39 self
._pmachines
.on_menu_enter()
42 self
._pmachines
.on_menu_exit()
44 def enterScene(self
, cls
):
45 self
._pmachines
.on_scene_enter(cls
)
48 self
._pmachines
.on_scene_exit()
58 SceneDominoBoxBasketball
,
60 SceneTeeterDominoBoxBasketball
]
63 info('platform: %s' % platform
)
64 info('exists main.py: %s' % exists('main.py'))
65 args
= self
._parse
_args
()
67 self
.base
= ShowBase()
68 self
._prepare
_window
(args
)
69 self
.updating
= args
.update
70 self
.version
= args
.version
73 self
._music
= MusicMgr(self
._options
['settings']['volume'])
74 self
.lang_mgr
= LangMgr(self
._options
['settings']['language'],
77 self
._fsm
= MainFsm(self
)
79 cls
= [cls
for cls
in self
.scenes
if cls
.__name
__ == args
.screenshot
][0]
80 scene
= cls(BulletWorld(), None, True, False, lambda: None, self
.scenes
)
84 elif self
._options
['development']['auto_start']:
85 mod_name
= 'game.scenes.scene_' + self
._options
['development']['auto_start']
86 for member
in import_module(mod_name
).__dict
__.values():
87 if isclass(member
) and issubclass(member
, Scene
) and \
90 self
._fsm
.demand('Scene', cls
)
92 self
._fsm
.demand('Menu')
94 def on_menu_enter(self
):
95 self
._menu
_bg
= Background()
97 self
._fsm
, self
.lang_mgr
, self
._options
, self
._music
,
98 self
._pipeline
, self
.scenes
)
101 self
._fsm
.demand('Menu')
103 def on_menu_exit(self
):
104 self
._menu
_bg
.destroy()
107 def on_scene_enter(self
, cls
):
110 self
.world
, self
.on_home
,
111 self
._options
['development']['auto_close_instructions'],
112 self
._options
['development']['debug_items'],
116 def on_scene_exit(self
):
117 self
._unset
_physics
()
118 self
._scene
.destroy()
120 def reload(self
, cls
):
121 self
._fsm
.demand('Scene', cls
)
123 def _configure(self
, args
):
124 load_prc_file_data('', 'window-title pmachines')
125 load_prc_file_data('', 'framebuffer-srgb true')
126 load_prc_file_data('', 'sync-video true')
127 # load_prc_file_data('', 'threading-model Cull/Draw')
128 # it freezes when you go to the next scene
130 load_prc_file_data('', 'window-type offscreen')
131 load_prc_file_data('', 'audio-library-name null')
133 def _parse_args(self
):
134 parser
= argparse
.ArgumentParser()
135 parser
.add_argument('--update', action
='store_true')
136 parser
.add_argument('--version', action
='store_true')
137 parser
.add_argument('--optfile')
138 parser
.add_argument('--screenshot')
139 cmd_line
= [arg
for arg
in iter(argv
[1:]) if not arg
.startswith('-psn_')]
140 args
= parser
.parse_args(cmd_line
)
143 def _prepare_window(self
, args
):
145 if (platform
.startswith('win') or platform
.startswith('linux')) and (
146 not exists('main.py') or __file__
.startswith('/app/bin/')):
147 # it is the deployed version for windows
148 data_path
= str(Filename
.get_user_appdata_directory()) + '/pmachines'
149 home
= '/home/flavio' # we must force this for wine
150 if data_path
.startswith('/c/users/') and exists(home
+ '/.wine/'):
151 data_path
= home
+ '/.wine/drive_' + data_path
[1:]
152 info('creating dirs: %s' % data_path
)
153 makedirs(data_path
, exist_ok
=True)
154 optfile
= args
.optfile
if args
.optfile
else 'options.ini'
155 info('data path: %s' % data_path
)
156 info('option file: %s' % optfile
)
157 info('fixed path: %s' % LibP3d
.fixpath(data_path
+ '/' + optfile
))
171 'auto_close_instructions': 0,
175 opt_path
= LibP3d
.fixpath(data_path
+ '/' + optfile
) if data_path
else optfile
176 opt_exists
= exists(opt_path
)
177 self
._options
= DctFile(
178 LibP3d
.fixpath(data_path
+ '/' + optfile
) if data_path
else optfile
,
181 self
._options
.store()
182 res
= self
._options
['settings']['resolution']
184 res
= LVector2i(*[int(_res
) for _res
in res
.split('x')])
186 d_i
= base
.pipe
.get_display_information()
188 return d_i
.get_display_mode_width(idx
), \
189 d_i
.get_display_mode_height(idx
)
191 _res(idx
) for idx
in range(d_i
.get_total_display_modes())]
192 res
= sorted(resolutions
)[-1]
193 props
= WindowProperties()
195 props
.set_fullscreen(self
._options
['settings']['fullscreen'])
196 props
.set_icon_filename('assets/images/icon/pmachines.ico')
197 if not args
.screenshot
:
198 base
.win
.request_properties(props
)
199 #gltf.patch_loader(base.loader)
200 if self
._options
['development']['simplepbr']:
201 self
._pipeline
= simplepbr
.init(
202 use_normal_maps
=True,
203 use_emission_maps
=False,
204 use_occlusion_maps
=True,
205 msaa_samples
=4 if self
._options
['settings']['antialiasing'] else 1,
206 enable_shadows
=int(self
._options
['settings']['shadows']))
207 debug(f
'msaa: {self._pipeline.msaa_samples}')
208 debug(f
'shadows: {self._pipeline.enable_shadows}')
209 render
.setAntialias(AntialiasAttrib
.MAuto
)
210 self
.base
.set_background_color(0, 0, 0, 1)
211 self
.base
.disable_mouse()
212 if self
._options
['development']['show_buffers']:
213 base
.bufferViewer
.toggleEnable()
214 if self
._options
['development']['fps']:
215 base
.set_frame_rate_meter(True)
216 #self.base.accept('window-event', self._on_win_evt)
217 self
.base
.accept('aspectRatioChanged', self
._on
_aspect
_ratio
_changed
)
219 def _set_physics(self
):
220 if self
._options
['development']['physics_debug']:
221 debug_node
= BulletDebugNode('Debug')
222 debug_node
.show_wireframe(True)
223 debug_node
.show_constraints(True)
224 debug_node
.show_bounding_boxes(True)
225 debug_node
.show_normals(True)
226 self
._debug
_np
= render
.attach_new_node(debug_node
)
227 self
._debug
_np
.show()
228 self
.world
= BulletWorld()
229 self
.world
.set_gravity((0, 0, -9.81))
230 if self
._options
['development']['physics_debug']:
231 self
.world
.set_debug_node(self
._debug
_np
.node())
233 dt
= globalClock
.get_dt()
234 self
.world
.do_physics(dt
, 10, 1/180)
236 self
._phys
_tsk
= taskMgr
.add(update
, 'update')
238 def _unset_physics(self
):
239 if self
._options
['development']['physics_debug']:
240 self
._debug
_np
.remove_node()
242 taskMgr
.remove(self
._phys
_tsk
)
244 def _on_aspect_ratio_changed(self
):
245 if self
._fsm
.state
== 'Scene':
246 self
._scene
.on_aspect_ratio_changed()