4 from sys
import platform
, argv
5 from logging
import info
, debug
6 from os
.path
import exists
7 from os
import makedirs
8 from panda3d
.core
import Filename
, load_prc_file_data
, AntialiasAttrib
, \
9 Texture
, WindowProperties
, LVector2i
10 from panda3d
.bullet
import BulletWorld
, BulletDebugNode
11 from direct
.showbase
.ShowBase
import ShowBase
12 from direct
.fsm
.FSM
import FSM
13 from pmachines
.music
import MusicMgr
14 from pmachines
.items
.background
import Background
15 from pmachines
.menu
import Menu
16 from lib
.dictfile
import DctFile
17 from lib
.lib
.p3d
.p3d
import LibP3d
18 from lib
.engine
.lang
import LangMgr
23 def __init__(self
, pmachines
):
24 super().__init
__('Main FSM')
25 self
._pmachines
= pmachines
28 self
._pmachines
.on_menu_enter()
31 self
._pmachines
.on_menu_exit()
33 def enterScene(self
, cls
):
34 self
._pmachines
.on_scene_enter(cls
)
37 self
._pmachines
.on_scene_exit()
44 self
.base
= ShowBase()
45 info('platform: %s' % platform
)
46 info('exists main.py: %s' % exists('main.py'))
47 args
= self
._parse
_args
()
48 self
._prepare
_window
(args
)
49 self
.updating
= args
.update
50 self
.version
= args
.version
53 self
._music
= MusicMgr(self
._options
['settings']['volume'])
54 self
.lang_mgr
= LangMgr(self
._options
['settings']['language'],
57 self
._fsm
= MainFsm(self
)
58 tgt_state
= 'Scene' if self
._options
['development']['auto_start'] else 'Menu'
59 self
._fsm
.demand(tgt_state
)
61 def on_menu_enter(self
):
62 self
._menu
_bg
= Background()
64 self
._fsm
, self
.lang_mgr
, self
._options
, self
._music
,
68 self
._fsm
.demand('Menu')
70 def on_menu_exit(self
):
71 self
._menu
_bg
.destroy()
74 def on_scene_enter(self
, cls
):
77 self
.world
, self
.on_home
,
78 self
._options
['development']['auto_close_instructions'],
79 self
._options
['development']['debug_items'])
81 def on_scene_exit(self
):
86 load_prc_file_data('', 'window-title pmachines')
87 load_prc_file_data('', 'framebuffer-srgb true')
88 load_prc_file_data('', 'sync-video true')
89 load_prc_file_data('', 'threading-model Cull/Draw')
91 def _parse_args(self
):
92 parser
= argparse
.ArgumentParser()
93 parser
.add_argument('--update', action
='store_true')
94 parser
.add_argument('--version', action
='store_true')
95 parser
.add_argument('--optfile')
96 cmd_line
= [arg
for arg
in iter(argv
[1:]) if not arg
.startswith('-psn_')]
97 args
= parser
.parse_args(cmd_line
)
100 def _prepare_window(self
, args
):
102 if (platform
.startswith('win') or platform
.startswith('linux')) and (
103 not exists('main.py') or __file__
.startswith('/app/bin/')):
104 # it is the deployed version for windows
105 data_path
= str(Filename
.get_user_appdata_directory()) + '/pmachines'
106 home
= '/home/flavio' # we must force this for wine
107 if data_path
.startswith('/c/users/') and exists(home
+ '/.wine/'):
108 data_path
= home
+ '/.wine/drive_' + data_path
[1:]
109 info('creating dirs: %s' % data_path
)
110 makedirs(data_path
, exist_ok
=True)
111 optfile
= args
.optfile
if args
.optfile
else 'options.ini'
112 info('data path: %s' % data_path
)
113 info('option file: %s' % optfile
)
114 info('fixed path: %s' % LibP3d
.fixpath(data_path
+ '/' + optfile
))
128 'auto_close_instructions': 0,
132 opt_path
= LibP3d
.fixpath(data_path
+ '/' + optfile
) if data_path
else optfile
133 opt_exists
= exists(opt_path
)
134 self
._options
= DctFile(
135 LibP3d
.fixpath(data_path
+ '/' + optfile
) if data_path
else optfile
,
138 self
._options
.store()
139 res
= self
._options
['settings']['resolution']
141 res
= LVector2i(*[int(_res
) for _res
in res
.split('x')])
143 d_i
= base
.pipe
.get_display_information()
145 return d_i
.get_display_mode_width(idx
), \
146 d_i
.get_display_mode_height(idx
)
148 _res(idx
) for idx
in range(d_i
.get_total_display_modes())]
149 res
= sorted(resolutions
)[-1]
150 props
= WindowProperties()
152 props
.set_fullscreen(self
._options
['settings']['fullscreen'])
153 props
.set_icon_filename('assets/icon/pmachines.ico')
154 base
.win
.request_properties(props
)
155 gltf
.patch_loader(base
.loader
)
156 if self
._options
['development']['simplepbr']:
157 self
._pipeline
= simplepbr
.init(
158 use_normal_maps
=True,
159 use_emission_maps
=False,
160 use_occlusion_maps
=True,
161 msaa_samples
=4 if self
._options
['settings']['antialiasing'] else 1,
162 enable_shadows
=int(self
._options
['settings']['shadows']))
163 debug(f
'msaa: {self._pipeline.msaa_samples}')
164 debug(f
'shadows: {self._pipeline.enable_shadows}')
165 render
.setAntialias(AntialiasAttrib
.MAuto
)
166 self
.base
.set_background_color(0, 0, 0, 1)
167 self
.base
.disable_mouse()
168 if self
._options
['development']['show_buffers']:
169 base
.bufferViewer
.toggleEnable()
170 if self
._options
['development']['fps']:
171 base
.set_frame_rate_meter(True)
172 #self.base.accept('window-event', self._on_win_evt)
173 self
.base
.accept('aspectRatioChanged', self
._on
_aspect
_ratio
_changed
)
175 def _set_physics(self
):
176 if self
._options
['development']['physics_debug']:
177 debug_node
= BulletDebugNode('Debug')
178 debug_node
.show_wireframe(True)
179 debug_node
.show_constraints(True)
180 debug_node
.show_bounding_boxes(True)
181 debug_node
.show_normals(True)
182 self
._debug
_np
= render
.attach_new_node(debug_node
)
183 self
._debug
_np
.show()
184 self
.world
= BulletWorld()
185 self
.world
.set_gravity((0, 0, -9.81))
186 if self
._options
['development']['physics_debug']:
187 self
.world
.set_debug_node(self
._debug
_np
.node())
189 dt
= globalClock
.get_dt()
190 self
.world
.do_physics(dt
)
192 self
._phys
_tsk
= taskMgr
.add(update
, 'update')
194 def _unset_physics(self
):
195 if self
._options
['development']['physics_debug']:
196 self
._debug
_np
.remove_node()
198 taskMgr
.remove(self
._phys
_tsk
)
200 def _on_aspect_ratio_changed(self
):
201 if self
._fsm
.state
== 'Scene':
202 self
._scene
.on_aspect_ratio_changed()