Commit | Line | Data |
---|---|---|
8ee66edd | 1 | import argparse |
4894bb48 FC |
2 | import simplepbr |
3 | import gltf | |
8ee66edd | 4 | from sys import platform, argv |
94a18c21 | 5 | from logging import info, debug |
8ee66edd FC |
6 | from os.path import exists |
7 | from os import makedirs | |
6fff1464 FC |
8 | from panda3d.core import Filename, load_prc_file_data, AntialiasAttrib, \ |
9 | Texture, WindowProperties, LVector2i | |
1be87278 | 10 | from panda3d.bullet import BulletWorld, BulletDebugNode |
8ee66edd | 11 | from direct.showbase.ShowBase import ShowBase |
5964572b | 12 | from direct.fsm.FSM import FSM |
1be87278 | 13 | from pmachines.scene import Scene |
54a1397e | 14 | from pmachines.music import MusicMgr |
5964572b | 15 | from pmachines.items.background import Background |
4071c6d8 | 16 | from pmachines.menu import Menu |
9ba5488b FC |
17 | from lib.dictfile import DctFile |
18 | from lib.lib.p3d.p3d import LibP3d | |
2aaa10d3 | 19 | from lib.engine.lang import LangMgr |
8ee66edd FC |
20 | |
21 | ||
5964572b FC |
22 | class MainFsm(FSM): |
23 | ||
24 | def __init__(self, pmachines): | |
25 | super().__init__('Main FSM') | |
26 | self._pmachines = pmachines | |
27 | ||
28 | def enterMenu(self): | |
29 | self._pmachines.on_menu_enter() | |
30 | ||
31 | def exitMenu(self): | |
32 | self._pmachines.on_menu_exit() | |
33 | ||
34 | def enterScene(self): | |
35 | self._pmachines.on_scene_enter() | |
36 | ||
37 | def exitScene(self): | |
38 | self._pmachines.on_scene_exit() | |
39 | ||
40 | ||
8ee66edd FC |
41 | class Pmachines: |
42 | ||
43 | def __init__(self): | |
44 | self._configure() | |
45 | self.base = ShowBase() | |
46 | info('platform: %s' % platform) | |
47 | info('exists main.py: %s' % exists('main.py')) | |
8ee66edd | 48 | args = self._parse_args() |
9ba5488b | 49 | self._prepare_window(args) |
8ee66edd FC |
50 | self.updating = args.update |
51 | self.version = args.version | |
52 | if args.update: | |
53 | return | |
e1e44d5c | 54 | self._music = MusicMgr(self._options['settings']['volume']) |
a0b33e12 | 55 | self.lang_mgr = LangMgr(self._options['settings']['language'], |
2aaa10d3 FC |
56 | 'pmachines', |
57 | 'assets/locale/') | |
5964572b | 58 | self._fsm = MainFsm(self) |
e669403e FC |
59 | tgt_state = 'Scene' if self._options['development']['auto_start'] else 'Menu' |
60 | self._fsm.demand(tgt_state) | |
5964572b FC |
61 | |
62 | def on_menu_enter(self): | |
63 | self._menu_bg = Background() | |
a9aba267 FC |
64 | self._menu = Menu( |
65 | self._fsm, self.lang_mgr, self._options, self._music, | |
66 | self._pipeline) | |
5964572b FC |
67 | |
68 | def on_home(self): | |
69 | self._fsm.demand('Menu') | |
70 | ||
71 | def on_menu_exit(self): | |
72 | self._menu_bg.destroy() | |
4071c6d8 | 73 | self._menu.destroy() |
5964572b FC |
74 | |
75 | def on_scene_enter(self): | |
1be87278 | 76 | self._set_physics() |
e669403e FC |
77 | self._scene = Scene( |
78 | self.world, self.on_home, | |
79 | self._options['development']['auto_close_instructions']) | |
5964572b FC |
80 | |
81 | def on_scene_exit(self): | |
82 | self._unset_physics() | |
83 | self._scene.destroy() | |
8ee66edd FC |
84 | |
85 | def _configure(self): | |
86 | load_prc_file_data('', 'window-title pmachines') | |
4894bb48 | 87 | load_prc_file_data('', 'framebuffer-srgb true') |
8ee66edd FC |
88 | |
89 | def _parse_args(self): | |
90 | parser = argparse.ArgumentParser() | |
91 | parser.add_argument('--update', action='store_true') | |
92 | parser.add_argument('--version', action='store_true') | |
9ba5488b | 93 | parser.add_argument('--optfile') |
8ee66edd FC |
94 | cmd_line = [arg for arg in iter(argv[1:]) if not arg.startswith('-psn_')] |
95 | args = parser.parse_args(cmd_line) | |
96 | return args | |
97 | ||
9ba5488b | 98 | def _prepare_window(self, args): |
8ee66edd FC |
99 | data_path = '' |
100 | if (platform.startswith('win') or platform.startswith('linux')) and ( | |
101 | not exists('main.py') or __file__.startswith('/app/bin/')): | |
102 | # it is the deployed version for windows | |
103 | data_path = str(Filename.get_user_appdata_directory()) + '/pmachines' | |
104 | home = '/home/flavio' # we must force this for wine | |
105 | if data_path.startswith('/c/users/') and exists(home + '/.wine/'): | |
106 | data_path = home + '/.wine/drive_' + data_path[1:] | |
107 | info('creating dirs: %s' % data_path) | |
108 | makedirs(data_path, exist_ok=True) | |
9ba5488b FC |
109 | optfile = args.optfile if args.optfile else 'options.ini' |
110 | info('data path: %s' % data_path) | |
111 | info('option file: %s' % optfile) | |
112 | info('fixed path: %s' % LibP3d.fixpath(data_path + '/' + optfile)) | |
113 | default_opt = { | |
114 | 'settings': { | |
a0b33e12 | 115 | 'volume': 1, |
6fff1464 FC |
116 | 'language': 'en', |
117 | 'fullscreen': 1, | |
a9aba267 | 118 | 'resolution': '', |
5fdf77d0 FC |
119 | 'antialiasing': 1, |
120 | 'shadows': 1}, | |
9ba5488b | 121 | 'development': { |
a5dc83f4 | 122 | 'simplepbr': 1, |
9ba5488b | 123 | 'verbose_log': 0, |
e669403e FC |
124 | 'physics_debug': 0, |
125 | 'auto_start': 0, | |
126 | 'auto_close_instructions': 0, | |
127 | 'show_buffers': 0}} | |
9ba5488b FC |
128 | opt_path = LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile |
129 | opt_exists = exists(opt_path) | |
130 | self._options = DctFile( | |
131 | LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile, | |
132 | default_opt) | |
133 | if not opt_exists: | |
134 | self._options.store() | |
6fff1464 FC |
135 | res = self._options['settings']['resolution'] |
136 | if res: | |
137 | res = LVector2i(*[int(_res) for _res in res.split('x')]) | |
138 | else: | |
139 | d_i = base.pipe.get_display_information() | |
140 | def _res(idx): | |
141 | return d_i.get_display_mode_width(idx), \ | |
142 | d_i.get_display_mode_height(idx) | |
143 | resolutions = [ | |
144 | _res(idx) for idx in range(d_i.get_total_display_modes())] | |
145 | res = sorted(resolutions)[-1] | |
146 | props = WindowProperties() | |
147 | props.set_size(res) | |
148 | props.set_fullscreen(self._options['settings']['fullscreen']) | |
94a18c21 | 149 | props.set_icon_filename('assets/icon/pmachines.ico') |
6fff1464 | 150 | base.win.request_properties(props) |
4894bb48 | 151 | gltf.patch_loader(base.loader) |
a5dc83f4 | 152 | if self._options['development']['simplepbr']: |
a9aba267 | 153 | self._pipeline = simplepbr.init( |
a5dc83f4 FC |
154 | use_normal_maps=True, |
155 | use_emission_maps=False, | |
a9aba267 | 156 | use_occlusion_maps=True, |
5fdf77d0 FC |
157 | msaa_samples=4 if self._options['settings']['antialiasing'] else 1, |
158 | enable_shadows=int(self._options['settings']['shadows'])) | |
94a18c21 FC |
159 | debug(f'msaa: {self._pipeline.msaa_samples}') |
160 | debug(f'shadows: {self._pipeline.enable_shadows}') | |
4894bb48 | 161 | render.setAntialias(AntialiasAttrib.MAuto) |
1be87278 FC |
162 | self.base.set_background_color(0, 0, 0, 1) |
163 | self.base.disable_mouse() | |
e669403e FC |
164 | if self._options['development']['show_buffers']: |
165 | base.bufferViewer.toggleEnable() | |
651713a9 FC |
166 | #self.base.accept('window-event', self._on_win_evt) |
167 | self.base.accept('aspectRatioChanged', self._on_aspect_ratio_changed) | |
1be87278 FC |
168 | |
169 | def _set_physics(self): | |
9ba5488b FC |
170 | if self._options['development']['physics_debug']: |
171 | debug_node = BulletDebugNode('Debug') | |
172 | debug_node.show_wireframe(True) | |
173 | debug_node.show_constraints(True) | |
174 | debug_node.show_bounding_boxes(True) | |
175 | debug_node.show_normals(True) | |
5964572b FC |
176 | self._debug_np = render.attach_new_node(debug_node) |
177 | self._debug_np.show() | |
1be87278 FC |
178 | self.world = BulletWorld() |
179 | self.world.set_gravity((0, 0, -9.81)) | |
9ba5488b | 180 | if self._options['development']['physics_debug']: |
5964572b | 181 | self.world.set_debug_node(self._debug_np.node()) |
1be87278 FC |
182 | def update(task): |
183 | dt = globalClock.get_dt() | |
184 | self.world.do_physics(dt) | |
185 | return task.cont | |
5964572b FC |
186 | self._phys_tsk = taskMgr.add(update, 'update') |
187 | ||
188 | def _unset_physics(self): | |
189 | if self._options['development']['physics_debug']: | |
190 | self._debug_np.remove_node() | |
191 | self.world = None | |
192 | taskMgr.remove(self._phys_tsk) | |
651713a9 FC |
193 | |
194 | def _on_aspect_ratio_changed(self): | |
5964572b FC |
195 | if self._fsm.state == 'Scene': |
196 | self._scene.on_aspect_ratio_changed() |