Commit | Line | Data |
---|---|---|
8ee66edd | 1 | import argparse |
4894bb48 | 2 | import simplepbr |
420ce99a | 3 | #import gltf |
63e7aeb2 | 4 | from glob import glob |
a2a89363 FC |
5 | from importlib import import_module |
6 | from inspect import isclass | |
63e7aeb2 | 7 | from sys import platform, argv, exit |
94a18c21 | 8 | from logging import info, debug |
8ee66edd FC |
9 | from os.path import exists |
10 | from os import makedirs | |
6fff1464 FC |
11 | from panda3d.core import Filename, load_prc_file_data, AntialiasAttrib, \ |
12 | Texture, WindowProperties, LVector2i | |
1be87278 | 13 | from panda3d.bullet import BulletWorld, BulletDebugNode |
8ee66edd | 14 | from direct.showbase.ShowBase import ShowBase |
5964572b | 15 | from direct.fsm.FSM import FSM |
a0462193 FC |
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 | |
6168d0c2 FC |
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 | |
9ba5488b FC |
27 | from lib.dictfile import DctFile |
28 | from lib.lib.p3d.p3d import LibP3d | |
2aaa10d3 | 29 | from lib.engine.lang import LangMgr |
edeef6f9 | 30 | from lib.engine.functional import FunctionalTest |
8ee66edd FC |
31 | |
32 | ||
5964572b FC |
33 | class MainFsm(FSM): |
34 | ||
35 | def __init__(self, pmachines): | |
36 | super().__init__('Main FSM') | |
37 | self._pmachines = pmachines | |
38 | ||
39 | def enterMenu(self): | |
40 | self._pmachines.on_menu_enter() | |
41 | ||
42 | def exitMenu(self): | |
43 | self._pmachines.on_menu_exit() | |
44 | ||
8c9bf90e FC |
45 | def enterScene(self, cls): |
46 | self._pmachines.on_scene_enter(cls) | |
5964572b FC |
47 | |
48 | def exitScene(self): | |
49 | self._pmachines.on_scene_exit() | |
50 | ||
51 | ||
c8035584 | 52 | class PmachinesApp: |
8ee66edd | 53 | |
6168d0c2 FC |
54 | scenes = [ |
55 | SceneDomino, | |
56 | SceneBox, | |
57 | SceneDominoBox, | |
58 | SceneBasketBall, | |
59 | SceneDominoBoxBasketball, | |
60 | SceneTeeterTooter, | |
61 | SceneTeeterDominoBoxBasketball] | |
62 | ||
8ee66edd | 63 | def __init__(self): |
8ee66edd FC |
64 | info('platform: %s' % platform) |
65 | info('exists main.py: %s' % exists('main.py')) | |
8ee66edd | 66 | args = self._parse_args() |
d18f757d FC |
67 | self._configure(args) |
68 | self.base = ShowBase() | |
9ba5488b | 69 | self._prepare_window(args) |
8ee66edd FC |
70 | self.updating = args.update |
71 | self.version = args.version | |
72 | if args.update: | |
73 | return | |
edeef6f9 FC |
74 | if args.functional_test and int(args.functional_test) == 1: |
75 | self._options['settings']['volume'] = 0 | |
e1e44d5c | 76 | self._music = MusicMgr(self._options['settings']['volume']) |
a0b33e12 | 77 | self.lang_mgr = LangMgr(self._options['settings']['language'], |
2aaa10d3 FC |
78 | 'pmachines', |
79 | 'assets/locale/') | |
5964572b | 80 | self._fsm = MainFsm(self) |
a747111f | 81 | if args.screenshot: |
6168d0c2 FC |
82 | cls = [cls for cls in self.scenes if cls.__name__ == args.screenshot][0] |
83 | scene = cls(BulletWorld(), None, True, False, lambda: None, self.scenes) | |
a747111f FC |
84 | scene.screenshot() |
85 | scene.destroy() | |
63e7aeb2 FC |
86 | exit() |
87 | elif self._options['development']['auto_start']: | |
a0462193 | 88 | mod_name = 'game.scenes.scene_' + self._options['development']['auto_start'] |
a2a89363 FC |
89 | for member in import_module(mod_name).__dict__.values(): |
90 | if isclass(member) and issubclass(member, Scene) and \ | |
91 | member != Scene: | |
92 | cls = member | |
93 | self._fsm.demand('Scene', cls) | |
94 | else: | |
95 | self._fsm.demand('Menu') | |
edeef6f9 FC |
96 | if args.functional_test or args.functional_ref: |
97 | FunctionalTest(args.functional_test, args.functional_ref) | |
5964572b FC |
98 | |
99 | def on_menu_enter(self): | |
100 | self._menu_bg = Background() | |
a9aba267 FC |
101 | self._menu = Menu( |
102 | self._fsm, self.lang_mgr, self._options, self._music, | |
6168d0c2 | 103 | self._pipeline, self.scenes) |
5964572b FC |
104 | |
105 | def on_home(self): | |
106 | self._fsm.demand('Menu') | |
107 | ||
108 | def on_menu_exit(self): | |
109 | self._menu_bg.destroy() | |
4071c6d8 | 110 | self._menu.destroy() |
5964572b | 111 | |
8c9bf90e | 112 | def on_scene_enter(self, cls): |
1be87278 | 113 | self._set_physics() |
8c9bf90e | 114 | self._scene = cls( |
e669403e | 115 | self.world, self.on_home, |
31237524 | 116 | self._options['development']['auto_close_instructions'], |
9914cfc9 | 117 | self._options['development']['debug_items'], |
6168d0c2 FC |
118 | self.reload, |
119 | self.scenes) | |
5964572b FC |
120 | |
121 | def on_scene_exit(self): | |
122 | self._unset_physics() | |
123 | self._scene.destroy() | |
8ee66edd | 124 | |
9914cfc9 FC |
125 | def reload(self, cls): |
126 | self._fsm.demand('Scene', cls) | |
127 | ||
d18f757d | 128 | def _configure(self, args): |
8ee66edd | 129 | load_prc_file_data('', 'window-title pmachines') |
4894bb48 | 130 | load_prc_file_data('', 'framebuffer-srgb true') |
a9e8696e | 131 | load_prc_file_data('', 'sync-video true') |
d982c0a5 FC |
132 | if args.functional_test or args.functional_ref: |
133 | load_prc_file_data('', 'win-size 1280 720') | |
134 | # otherwise it is not centered in exwm | |
9914cfc9 FC |
135 | # load_prc_file_data('', 'threading-model Cull/Draw') |
136 | # it freezes when you go to the next scene | |
a747111f | 137 | if args.screenshot: |
d18f757d FC |
138 | load_prc_file_data('', 'window-type offscreen') |
139 | load_prc_file_data('', 'audio-library-name null') | |
8ee66edd FC |
140 | |
141 | def _parse_args(self): | |
142 | parser = argparse.ArgumentParser() | |
143 | parser.add_argument('--update', action='store_true') | |
144 | parser.add_argument('--version', action='store_true') | |
9ba5488b | 145 | parser.add_argument('--optfile') |
a747111f | 146 | parser.add_argument('--screenshot') |
edeef6f9 FC |
147 | parser.add_argument('--functional-test') |
148 | parser.add_argument('--functional-ref', action='store_true') | |
8ee66edd FC |
149 | cmd_line = [arg for arg in iter(argv[1:]) if not arg.startswith('-psn_')] |
150 | args = parser.parse_args(cmd_line) | |
151 | return args | |
152 | ||
9ba5488b | 153 | def _prepare_window(self, args): |
8ee66edd FC |
154 | data_path = '' |
155 | if (platform.startswith('win') or platform.startswith('linux')) and ( | |
156 | not exists('main.py') or __file__.startswith('/app/bin/')): | |
157 | # it is the deployed version for windows | |
158 | data_path = str(Filename.get_user_appdata_directory()) + '/pmachines' | |
159 | home = '/home/flavio' # we must force this for wine | |
160 | if data_path.startswith('/c/users/') and exists(home + '/.wine/'): | |
161 | data_path = home + '/.wine/drive_' + data_path[1:] | |
162 | info('creating dirs: %s' % data_path) | |
163 | makedirs(data_path, exist_ok=True) | |
9ba5488b FC |
164 | optfile = args.optfile if args.optfile else 'options.ini' |
165 | info('data path: %s' % data_path) | |
166 | info('option file: %s' % optfile) | |
167 | info('fixed path: %s' % LibP3d.fixpath(data_path + '/' + optfile)) | |
168 | default_opt = { | |
169 | 'settings': { | |
a0b33e12 | 170 | 'volume': 1, |
6fff1464 FC |
171 | 'language': 'en', |
172 | 'fullscreen': 1, | |
a9aba267 | 173 | 'resolution': '', |
5fdf77d0 FC |
174 | 'antialiasing': 1, |
175 | 'shadows': 1}, | |
9ba5488b | 176 | 'development': { |
a5dc83f4 | 177 | 'simplepbr': 1, |
9ba5488b | 178 | 'verbose_log': 0, |
e669403e FC |
179 | 'physics_debug': 0, |
180 | 'auto_start': 0, | |
181 | 'auto_close_instructions': 0, | |
31237524 | 182 | 'show_buffers': 0, |
b41381b2 FC |
183 | 'debug_items': 0, |
184 | 'fps': 0}} | |
9ba5488b FC |
185 | opt_path = LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile |
186 | opt_exists = exists(opt_path) | |
187 | self._options = DctFile( | |
188 | LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile, | |
189 | default_opt) | |
190 | if not opt_exists: | |
191 | self._options.store() | |
6fff1464 FC |
192 | res = self._options['settings']['resolution'] |
193 | if res: | |
194 | res = LVector2i(*[int(_res) for _res in res.split('x')]) | |
195 | else: | |
196 | d_i = base.pipe.get_display_information() | |
197 | def _res(idx): | |
198 | return d_i.get_display_mode_width(idx), \ | |
199 | d_i.get_display_mode_height(idx) | |
200 | resolutions = [ | |
201 | _res(idx) for idx in range(d_i.get_total_display_modes())] | |
202 | res = sorted(resolutions)[-1] | |
edeef6f9 | 203 | fullscreen = self._options['settings']['fullscreen'] |
d982c0a5 | 204 | props = WindowProperties() |
edeef6f9 | 205 | if args.functional_test or args.functional_ref: |
edeef6f9 | 206 | fullscreen = False |
d982c0a5 FC |
207 | else: |
208 | props.set_size(res) | |
edeef6f9 | 209 | props.set_fullscreen(fullscreen) |
7e487769 | 210 | props.set_icon_filename('assets/images/icon/pmachines.ico') |
a747111f | 211 | if not args.screenshot: |
d18f757d | 212 | base.win.request_properties(props) |
420ce99a | 213 | #gltf.patch_loader(base.loader) |
a5dc83f4 | 214 | if self._options['development']['simplepbr']: |
a9aba267 | 215 | self._pipeline = simplepbr.init( |
a5dc83f4 FC |
216 | use_normal_maps=True, |
217 | use_emission_maps=False, | |
a9aba267 | 218 | use_occlusion_maps=True, |
5fdf77d0 FC |
219 | msaa_samples=4 if self._options['settings']['antialiasing'] else 1, |
220 | enable_shadows=int(self._options['settings']['shadows'])) | |
94a18c21 FC |
221 | debug(f'msaa: {self._pipeline.msaa_samples}') |
222 | debug(f'shadows: {self._pipeline.enable_shadows}') | |
4894bb48 | 223 | render.setAntialias(AntialiasAttrib.MAuto) |
1be87278 FC |
224 | self.base.set_background_color(0, 0, 0, 1) |
225 | self.base.disable_mouse() | |
e669403e FC |
226 | if self._options['development']['show_buffers']: |
227 | base.bufferViewer.toggleEnable() | |
b41381b2 FC |
228 | if self._options['development']['fps']: |
229 | base.set_frame_rate_meter(True) | |
651713a9 FC |
230 | #self.base.accept('window-event', self._on_win_evt) |
231 | self.base.accept('aspectRatioChanged', self._on_aspect_ratio_changed) | |
1be87278 FC |
232 | |
233 | def _set_physics(self): | |
9ba5488b FC |
234 | if self._options['development']['physics_debug']: |
235 | debug_node = BulletDebugNode('Debug') | |
236 | debug_node.show_wireframe(True) | |
237 | debug_node.show_constraints(True) | |
238 | debug_node.show_bounding_boxes(True) | |
239 | debug_node.show_normals(True) | |
5964572b FC |
240 | self._debug_np = render.attach_new_node(debug_node) |
241 | self._debug_np.show() | |
1be87278 FC |
242 | self.world = BulletWorld() |
243 | self.world.set_gravity((0, 0, -9.81)) | |
9ba5488b | 244 | if self._options['development']['physics_debug']: |
5964572b | 245 | self.world.set_debug_node(self._debug_np.node()) |
1be87278 FC |
246 | def update(task): |
247 | dt = globalClock.get_dt() | |
0625cf49 | 248 | self.world.do_physics(dt, 10, 1/180) |
1be87278 | 249 | return task.cont |
5964572b FC |
250 | self._phys_tsk = taskMgr.add(update, 'update') |
251 | ||
252 | def _unset_physics(self): | |
253 | if self._options['development']['physics_debug']: | |
254 | self._debug_np.remove_node() | |
255 | self.world = None | |
256 | taskMgr.remove(self._phys_tsk) | |
651713a9 FC |
257 | |
258 | def _on_aspect_ratio_changed(self): | |
5964572b FC |
259 | if self._fsm.state == 'Scene': |
260 | self._scene.on_aspect_ratio_changed() |