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
.scene
import Scene
14 from pmachines
.music
import MusicMgr
15 from pmachines
.items
.background
import Background
16 from pmachines
.menu
import Menu
17 from lib
.dictfile
import DctFile
18 from lib
.lib
.p3d
.p3d
import LibP3d
19 from lib
.engine
.lang
import LangMgr
24 def __init__(self
, pmachines
):
25 super().__init
__('Main FSM')
26 self
._pmachines
= pmachines
29 self
._pmachines
.on_menu_enter()
32 self
._pmachines
.on_menu_exit()
35 self
._pmachines
.on_scene_enter()
38 self
._pmachines
.on_scene_exit()
45 self
.base
= ShowBase()
46 info('platform: %s' % platform
)
47 info('exists main.py: %s' % exists('main.py'))
48 args
= self
._parse
_args
()
49 self
._prepare
_window
(args
)
50 self
.updating
= args
.update
51 self
.version
= args
.version
54 self
._music
= MusicMgr(self
._options
['settings']['volume'])
55 self
.lang_mgr
= LangMgr(self
._options
['settings']['language'],
58 self
._fsm
= MainFsm(self
)
59 tgt_state
= 'Scene' if self
._options
['development']['auto_start'] else 'Menu'
60 self
._fsm
.demand(tgt_state
)
62 def on_menu_enter(self
):
63 self
._menu
_bg
= Background()
65 self
._fsm
, self
.lang_mgr
, self
._options
, self
._music
,
69 self
._fsm
.demand('Menu')
71 def on_menu_exit(self
):
72 self
._menu
_bg
.destroy()
75 def on_scene_enter(self
):
78 self
.world
, self
.on_home
,
79 self
._options
['development']['auto_close_instructions'],
80 self
._options
['development']['debug_items'])
82 def on_scene_exit(self
):
87 load_prc_file_data('', 'window-title pmachines')
88 load_prc_file_data('', 'framebuffer-srgb true')
90 def _parse_args(self
):
91 parser
= argparse
.ArgumentParser()
92 parser
.add_argument('--update', action
='store_true')
93 parser
.add_argument('--version', action
='store_true')
94 parser
.add_argument('--optfile')
95 cmd_line
= [arg
for arg
in iter(argv
[1:]) if not arg
.startswith('-psn_')]
96 args
= parser
.parse_args(cmd_line
)
99 def _prepare_window(self
, args
):
101 if (platform
.startswith('win') or platform
.startswith('linux')) and (
102 not exists('main.py') or __file__
.startswith('/app/bin/')):
103 # it is the deployed version for windows
104 data_path
= str(Filename
.get_user_appdata_directory()) + '/pmachines'
105 home
= '/home/flavio' # we must force this for wine
106 if data_path
.startswith('/c/users/') and exists(home
+ '/.wine/'):
107 data_path
= home
+ '/.wine/drive_' + data_path
[1:]
108 info('creating dirs: %s' % data_path
)
109 makedirs(data_path
, exist_ok
=True)
110 optfile
= args
.optfile
if args
.optfile
else 'options.ini'
111 info('data path: %s' % data_path
)
112 info('option file: %s' % optfile
)
113 info('fixed path: %s' % LibP3d
.fixpath(data_path
+ '/' + optfile
))
127 'auto_close_instructions': 0,
131 opt_path
= LibP3d
.fixpath(data_path
+ '/' + optfile
) if data_path
else optfile
132 opt_exists
= exists(opt_path
)
133 self
._options
= DctFile(
134 LibP3d
.fixpath(data_path
+ '/' + optfile
) if data_path
else optfile
,
137 self
._options
.store()
138 res
= self
._options
['settings']['resolution']
140 res
= LVector2i(*[int(_res
) for _res
in res
.split('x')])
142 d_i
= base
.pipe
.get_display_information()
144 return d_i
.get_display_mode_width(idx
), \
145 d_i
.get_display_mode_height(idx
)
147 _res(idx
) for idx
in range(d_i
.get_total_display_modes())]
148 res
= sorted(resolutions
)[-1]
149 props
= WindowProperties()
151 props
.set_fullscreen(self
._options
['settings']['fullscreen'])
152 props
.set_icon_filename('assets/icon/pmachines.ico')
153 base
.win
.request_properties(props
)
154 gltf
.patch_loader(base
.loader
)
155 if self
._options
['development']['simplepbr']:
156 self
._pipeline
= simplepbr
.init(
157 use_normal_maps
=True,
158 use_emission_maps
=False,
159 use_occlusion_maps
=True,
160 msaa_samples
=4 if self
._options
['settings']['antialiasing'] else 1,
161 enable_shadows
=int(self
._options
['settings']['shadows']))
162 debug(f
'msaa: {self._pipeline.msaa_samples}')
163 debug(f
'shadows: {self._pipeline.enable_shadows}')
164 render
.setAntialias(AntialiasAttrib
.MAuto
)
165 self
.base
.set_background_color(0, 0, 0, 1)
166 self
.base
.disable_mouse()
167 if self
._options
['development']['show_buffers']:
168 base
.bufferViewer
.toggleEnable()
169 if self
._options
['development']['fps']:
170 base
.set_frame_rate_meter(True)
171 #self.base.accept('window-event', self._on_win_evt)
172 self
.base
.accept('aspectRatioChanged', self
._on
_aspect
_ratio
_changed
)
174 def _set_physics(self
):
175 if self
._options
['development']['physics_debug']:
176 debug_node
= BulletDebugNode('Debug')
177 debug_node
.show_wireframe(True)
178 debug_node
.show_constraints(True)
179 debug_node
.show_bounding_boxes(True)
180 debug_node
.show_normals(True)
181 self
._debug
_np
= render
.attach_new_node(debug_node
)
182 self
._debug
_np
.show()
183 self
.world
= BulletWorld()
184 self
.world
.set_gravity((0, 0, -9.81))
185 if self
._options
['development']['physics_debug']:
186 self
.world
.set_debug_node(self
._debug
_np
.node())
188 dt
= globalClock
.get_dt()
189 self
.world
.do_physics(dt
)
191 self
._phys
_tsk
= taskMgr
.add(update
, 'update')
193 def _unset_physics(self
):
194 if self
._options
['development']['physics_debug']:
195 self
._debug
_np
.remove_node()
197 taskMgr
.remove(self
._phys
_tsk
)
199 def _on_aspect_ratio_changed(self
):
200 if self
._fsm
.state
== 'Scene':
201 self
._scene
.on_aspect_ratio_changed()