Commit | Line | Data |
---|---|---|
31237524 | 1 | from os.path import exists |
a0462193 | 2 | from os import makedirs |
c991401b | 3 | from logging import info |
3fe18d73 | 4 | from json import loads |
c991401b FC |
5 | from panda3d.core import AmbientLight, Texture, TextPropertiesManager, \ |
6 | TextNode, Spotlight, PerspectiveLens, BitMask32, NodePath | |
36099535 FC |
7 | from panda3d.bullet import BulletPlaneShape, BulletGhostNode |
8 | from direct.gui.OnscreenImage import OnscreenImage | |
2aaa10d3 FC |
9 | from direct.gui.OnscreenText import OnscreenText |
10 | from direct.gui.DirectGui import DirectButton, DirectFrame | |
36099535 | 11 | from direct.gui.DirectGuiGlobals import FLAT, DISABLED, NORMAL |
1be87278 | 12 | from direct.showbase.DirectObject import DirectObject |
fe0a68a0 FC |
13 | from direct.interval.IntervalGlobal import Sequence, Func |
14 | from direct.interval.LerpInterval import LerpFunctionInterval | |
4586cbf6 FC |
15 | from pmachines.items.background import Background |
16 | from pmachines.gui.sidepanel import SidePanel | |
b35b1f62 FC |
17 | from ya2.utils.cursor import MouseCursor |
18 | from ya2.p3d.gfx import P3dGfxMgr | |
2d1773b1 | 19 | from ya2.p3d.p3d import LibP3d |
1be87278 FC |
20 | |
21 | ||
22 | class Scene(DirectObject): | |
23 | ||
92c29685 | 24 | scenes_done = [] |
3fe18d73 | 25 | json = {} |
92c29685 FC |
26 | |
27 | def __init__(self, world, exit_cb, auto_close_instr, dbg_items, reload_cb, scenes, pos_mgr, testing, mouse_coords, persistent): | |
1be87278 FC |
28 | super().__init__() |
29 | self._world = world | |
5964572b | 30 | self._exit_cb = exit_cb |
ce302b41 | 31 | self._testing = testing |
7fa58640 | 32 | self._mouse_coords = mouse_coords |
31237524 | 33 | self._dbg_items = dbg_items |
9914cfc9 | 34 | self._reload_cb = reload_cb |
2d1773b1 FC |
35 | self._pos_mgr = pos_mgr |
36 | self._pos_mgr.reset() | |
6168d0c2 | 37 | self._scenes = scenes |
ce302b41 | 38 | self._start_evt_time = None |
fa3662a6 | 39 | self._enforce_res = '' |
92c29685 | 40 | self.__persistent = persistent |
fa3662a6 | 41 | self.accept('enforce_res', self.enforce_res) |
1be87278 | 42 | self._set_camera() |
79f81d48 | 43 | self._cursor = MouseCursor( |
7e487769 | 44 | 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1), |
79f81d48 | 45 | (.01, .01)) |
36099535 | 46 | self._set_gui() |
1be87278 FC |
47 | self._set_lights() |
48 | self._set_input() | |
c8d8653f | 49 | self._set_mouse_plane() |
d5932612 | 50 | self.items = [] |
067a36db | 51 | self._test_items = [] |
d5932612 | 52 | self.reset() |
0a0994e4 | 53 | self._state = 'init' |
9830561d | 54 | self._paused = False |
7c0a81ae | 55 | self._item_active = None |
e669403e | 56 | if auto_close_instr: |
32aa4dae | 57 | self.__store_state() |
e669403e FC |
58 | self.__restore_state() |
59 | else: | |
60 | self._set_instructions() | |
5964572b FC |
61 | self._bg = Background() |
62 | self._side_panel = SidePanel(world, self._mouse_plane_node, (-5, 4), (-3, 1), 1, self.items) | |
63 | self._scene_tsk = taskMgr.add(self.on_frame, 'on_frame') | |
64 | ||
8c9bf90e FC |
65 | @staticmethod |
66 | def name(): | |
67 | return '' | |
68 | ||
3fe18d73 FC |
69 | @classmethod |
70 | def version(cls): | |
71 | if not cls.json: | |
72 | with open(cls.filename) as f: | |
73 | cls.json = loads(f.read()) | |
74 | return cls.json['version'] | |
75 | ||
92c29685 FC |
76 | @classmethod |
77 | def is_done(cls): | |
3fe18d73 | 78 | return bool([(name, version) for name, version in cls.scenes_done if cls.__name__ == name and cls.version() == version]) |
92c29685 | 79 | |
0eff64a3 FC |
80 | def _instr_txt(self): |
81 | return '' | |
82 | ||
83 | def _set_items(self): | |
84 | self.items = [] | |
067a36db | 85 | self._test_items = [] |
0eff64a3 | 86 | |
0d5a5427 | 87 | def screenshot(self, task=None): |
ecdf8933 FC |
88 | tex = Texture('screenshot') |
89 | buffer = base.win.make_texture_buffer('screenshot', 512, 512, tex, True ) | |
90 | cam = base.make_camera(buffer) | |
91 | cam.reparent_to(render) | |
92 | cam.node().get_lens().set_fov(base.camLens.get_fov()) | |
93 | cam.set_pos(0, -20, 0) | |
94 | cam.look_at(0, 0, 0) | |
95 | import simplepbr | |
96 | simplepbr.init( | |
97 | window=buffer, | |
98 | camera_node=cam, | |
99 | use_normal_maps=True, | |
100 | use_emission_maps=False, | |
101 | use_occlusion_maps=True, | |
102 | msaa_samples=4, | |
103 | enable_shadows=True) | |
104 | base.graphicsEngine.renderFrame() | |
105 | base.graphicsEngine.renderFrame() | |
63e7aeb2 | 106 | fname = self.__class__.__name__ |
40cc6e36 FC |
107 | if not exists('assets/images/scenes'): |
108 | makedirs('assets/images/scenes') | |
63e7aeb2 | 109 | buffer.save_screenshot('assets/images/scenes/%s.png' % fname) |
ecdf8933 FC |
110 | # img = DirectButton( |
111 | # frameTexture=buffer.get_texture(), relief=FLAT, | |
112 | # frameSize=(-.2, .2, -.2, .2)) | |
0d5a5427 | 113 | return buffer.get_texture() |
ecdf8933 | 114 | |
d5932612 FC |
115 | def current_bottom(self): |
116 | curr_bottom = 1 | |
117 | for item in self.items: | |
118 | if item.repos_done: | |
119 | curr_bottom = min(curr_bottom, item.get_bottom()) | |
120 | return curr_bottom | |
121 | ||
05fd23ec | 122 | def reset(self): |
d5932612 | 123 | [itm.destroy() for itm in self.items] |
067a36db FC |
124 | [itm.remove_node() for itm in self._test_items] |
125 | self.items = [] | |
126 | self._test_items = [] | |
0eff64a3 | 127 | self._set_items() |
067a36db | 128 | self._set_test_items() |
0a0994e4 | 129 | self._state = 'init' |
32aa4dae FC |
130 | self._commands = [] |
131 | self._command_idx = 0 | |
ce302b41 | 132 | self._start_evt_time = None |
b41381b2 FC |
133 | if hasattr(self, '_success_txt'): |
134 | self._success_txt.destroy() | |
135 | del self._success_txt | |
136 | self.__right_btn['state'] = NORMAL | |
05fd23ec | 137 | |
fa3662a6 FC |
138 | def enforce_res(self, val): |
139 | self._enforce_res = val | |
74ed9732 | 140 | info('enforce res: ' + val) |
fa3662a6 | 141 | |
5964572b | 142 | def destroy(self): |
fe0a68a0 | 143 | self.__intro_sequence.finish() |
fa3662a6 | 144 | self.ignore('enforce_res') |
5964572b FC |
145 | self._unset_gui() |
146 | self._unset_lights() | |
147 | self._unset_input() | |
148 | self._unset_mouse_plane() | |
149 | [itm.destroy() for itm in self.items] | |
067a36db | 150 | [itm.remove_node() for itm in self._test_items] |
5964572b FC |
151 | self._bg.destroy() |
152 | self._side_panel.destroy() | |
407412a5 | 153 | self._cursor.destroy() |
5964572b | 154 | taskMgr.remove(self._scene_tsk) |
9fc7f6fb FC |
155 | if hasattr(self, '_success_txt'): |
156 | self._success_txt.destroy() | |
1be87278 FC |
157 | |
158 | def _set_camera(self): | |
159 | base.camera.set_pos(0, -20, 0) | |
160 | base.camera.look_at(0, 0, 0) | |
fe0a68a0 FC |
161 | def camera_ani(t): |
162 | start_v = (1, -5, 1) | |
163 | end_v = (0, -20, 0) | |
164 | curr_pos = ( | |
165 | start_v[0] + (end_v[0] - start_v[0]) * t, | |
166 | start_v[1] + (end_v[1] - start_v[1]) * t, | |
167 | start_v[2] + (end_v[2] - start_v[2]) * t) | |
168 | base.camera.set_pos(*curr_pos) | |
169 | self.repos() | |
170 | camera_interval = LerpFunctionInterval( | |
171 | camera_ani, | |
172 | 1.2, | |
173 | 0, | |
174 | 1, | |
175 | blendType='easeInOut') | |
176 | self.__intro_sequence = Sequence( | |
177 | camera_interval, | |
178 | Func(self.repos)) | |
179 | self.__intro_sequence.start() | |
1be87278 | 180 | |
a0acba9a | 181 | def __load_img_btn(self, path, col): |
7e487769 | 182 | img = OnscreenImage('assets/images/buttons/%s.dds' % path) |
a0acba9a FC |
183 | img.set_transparency(True) |
184 | img.set_color(col) | |
185 | img.detach_node() | |
186 | return img | |
187 | ||
36099535 | 188 | def _set_gui(self): |
01b221a6 FC |
189 | def load_images_btn(path, col): |
190 | colors = { | |
191 | 'gray': [ | |
192 | (.6, .6, .6, 1), # ready | |
193 | (1, 1, 1, 1), # press | |
194 | (.8, .8, .8, 1), # rollover | |
195 | (.4, .4, .4, .4)], | |
196 | 'green': [ | |
197 | (.1, .68, .1, 1), | |
198 | (.1, 1, .1, 1), | |
199 | (.1, .84, .1, 1), | |
200 | (.4, .1, .1, .4)]}[col] | |
a0acba9a | 201 | return [self.__load_img_btn(path, col) for col in colors] |
36099535 FC |
202 | abl, abr = base.a2dBottomLeft, base.a2dBottomRight |
203 | btn_info = [ | |
5964572b | 204 | ('home', self.on_home, NORMAL, abl, 'gray'), |
9830561d | 205 | ('information', self._set_instructions, NORMAL, abl, 'gray'), |
01b221a6 | 206 | ('right', self.on_play, NORMAL, abr, 'green'), |
f26497a5 FC |
207 | #('next', self.on_next, DISABLED, abr, 'gray'), |
208 | #('previous', self.on_prev, DISABLED, abr, 'gray'), | |
209 | #('rewind', self.reset, NORMAL, abr, 'gray') | |
210 | ] | |
36099535 | 211 | num_l = num_r = 0 |
a0acba9a | 212 | btns = [] |
36099535 | 213 | for binfo in btn_info: |
01b221a6 | 214 | imgs = load_images_btn(binfo[0], binfo[4]) |
36099535 FC |
215 | if binfo[3] == base.a2dBottomLeft: |
216 | sign, num = 1, num_l | |
217 | num_l += 1 | |
218 | else: | |
219 | sign, num = -1, num_r | |
220 | num_r += 1 | |
221 | fcols = (.4, .4, .4, .14), (.3, .3, .3, .05) | |
222 | btn = DirectButton( | |
223 | image=imgs, scale=.05, pos=(sign * (.06 + .11 * num), 1, .06), | |
224 | parent=binfo[3], command=binfo[1], state=binfo[2], relief=FLAT, | |
54a1397e FC |
225 | frameColor=fcols[0] if binfo[2] == NORMAL else fcols[1], |
226 | rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'), | |
227 | clickSound=loader.load_sfx('assets/audio/sfx/click.ogg')) | |
36099535 | 228 | btn.set_transparency(True) |
2d1773b1 | 229 | self._pos_mgr.register(binfo[0], LibP3d.wdg_pos(btn)) |
a0acba9a | 230 | btns += [btn] |
f26497a5 FC |
231 | self.__home_btn, self.__info_btn, self.__right_btn = btns |
232 | # , self.__next_btn, self.__prev_btn, self.__rewind_btn | |
31237524 FC |
233 | if self._dbg_items: |
234 | self._info_txt = OnscreenText( | |
235 | '', parent=base.a2dTopRight, scale=0.04, | |
236 | pos=(-.03, -.06), fg=(.9, .9, .9, 1), align=TextNode.A_right) | |
7fa58640 FC |
237 | if self._mouse_coords: |
238 | self._coords_txt = OnscreenText( | |
239 | '', parent=base.a2dTopRight, scale=0.04, | |
240 | pos=(-.03, -.12), fg=(.9, .9, .9, 1), align=TextNode.A_right) | |
241 | def update_coords(task): | |
242 | pos = None | |
243 | for hit in self._get_hits(): | |
244 | if hit.get_node() == self._mouse_plane_node: | |
245 | pos = hit.get_hit_pos() | |
246 | if pos: | |
247 | txt = '%s %s' % (round(pos.x, 3), | |
248 | round(pos.z, 3)) | |
249 | self._coords_txt['text'] = txt | |
250 | return task.cont | |
251 | self._coords_tsk = taskMgr.add(update_coords, 'update_coords') | |
36099535 | 252 | |
5964572b FC |
253 | def _unset_gui(self): |
254 | btns = [ | |
255 | self.__home_btn, self.__info_btn, self.__right_btn, | |
f26497a5 FC |
256 | #self.__next_btn, self.__prev_btn, self.__rewind_btn |
257 | ] | |
5964572b | 258 | [btn.destroy() for btn in btns] |
31237524 FC |
259 | if self._dbg_items: |
260 | self._info_txt.destroy() | |
7fa58640 FC |
261 | if self._mouse_coords: |
262 | taskMgr.remove(self._coords_tsk) | |
263 | self._coords_txt.destroy() | |
5964572b | 264 | |
64eae9c7 FC |
265 | def _set_spotlight(self, name, pos, look_at, color, shadows=False): |
266 | light = Spotlight(name) | |
267 | if shadows: | |
268 | light.setLens(PerspectiveLens()) | |
1be87278 | 269 | light_np = render.attach_new_node(light) |
64eae9c7 FC |
270 | light_np.set_pos(pos) |
271 | light_np.look_at(look_at) | |
1be87278 FC |
272 | light.set_color(color) |
273 | render.set_light(light_np) | |
5964572b | 274 | return light_np |
1be87278 FC |
275 | |
276 | def _set_lights(self): | |
277 | alight = AmbientLight('alight') # for ao | |
64eae9c7 FC |
278 | alight.set_color((.15, .15, .15, 1)) |
279 | self._alnp = render.attach_new_node(alight) | |
280 | render.set_light(self._alnp) | |
281 | self._key_light = self._set_spotlight( | |
282 | 'key light', (-5, -80, 5), (0, 0, 0), (2.8, 2.8, 2.8, 1)) | |
283 | self._shadow_light = self._set_spotlight( | |
284 | 'key light', (-5, -80, 5), (0, 0, 0), (.58, .58, .58, 1), True) | |
285 | self._shadow_light.node().set_shadow_caster(True, 2048, 2048) | |
286 | self._shadow_light.node().get_lens().set_film_size(2048, 2048) | |
287 | self._shadow_light.node().get_lens().set_near_far(1, 256) | |
288 | self._shadow_light.node().set_camera_mask(BitMask32(0x01)) | |
5964572b FC |
289 | |
290 | def _unset_lights(self): | |
64eae9c7 | 291 | for light in [self._alnp, self._key_light, self._shadow_light]: |
5964572b FC |
292 | render.clear_light(light) |
293 | light.remove_node() | |
1be87278 FC |
294 | |
295 | def _set_input(self): | |
49c79300 | 296 | self.accept('mouse1', self.on_click_l) |
c8d8653f | 297 | self.accept('mouse1-up', self.on_release) |
49c79300 FC |
298 | self.accept('mouse3', self.on_click_r) |
299 | self.accept('mouse3-up', self.on_release) | |
c8d8653f | 300 | |
5964572b FC |
301 | def _unset_input(self): |
302 | for evt in ['mouse1', 'mouse1-up', 'mouse3', 'mouse3-up']: | |
303 | self.ignore(evt) | |
304 | ||
c8d8653f | 305 | def _set_mouse_plane(self): |
651713a9 | 306 | shape = BulletPlaneShape((0, -1, 0), 0) |
c8d8653f FC |
307 | #self._mouse_plane_node = BulletRigidBodyNode('mouse plane') |
308 | self._mouse_plane_node = BulletGhostNode('mouse plane') | |
309 | self._mouse_plane_node.addShape(shape) | |
310 | #np = render.attachNewNode(self._mouse_plane_node) | |
311 | #self._world.attachRigidBody(self._mouse_plane_node) | |
06af3aa9 | 312 | self._world.attach_ghost(self._mouse_plane_node) |
1be87278 | 313 | |
5964572b FC |
314 | def _unset_mouse_plane(self): |
315 | self._world.remove_ghost(self._mouse_plane_node) | |
316 | ||
37ba71d8 FC |
317 | def _get_hits(self): |
318 | if not base.mouseWatcherNode.has_mouse(): return [] | |
13263131 | 319 | p_from, p_to = P3dGfxMgr.world_from_to(base.mouseWatcherNode.get_mouse()) |
37ba71d8 FC |
320 | return self._world.ray_test_all(p_from, p_to).get_hits() |
321 | ||
31237524 FC |
322 | def _update_info(self, item): |
323 | txt = '' | |
324 | if item: | |
325 | txt = '%.3f %.3f\n%.3f°' % ( | |
326 | item._np.get_x(), item._np.get_z(), item._np.get_r()) | |
327 | self._info_txt['text'] = txt | |
328 | ||
49c79300 | 329 | def _on_click(self, method): |
a0acba9a FC |
330 | if self._paused: |
331 | return | |
c8d8653f FC |
332 | for hit in self._get_hits(): |
333 | if hit.get_node() == self._mouse_plane_node: | |
334 | pos = hit.get_hit_pos() | |
37ba71d8 | 335 | for hit in self._get_hits(): |
ef3c36bf | 336 | for item in [i for i in self.items if hit.get_node() == i.node and i.interactable]: |
7c0a81ae FC |
337 | if not self._item_active: |
338 | self._item_active = item | |
49c79300 | 339 | getattr(item, method)(pos) |
79f81d48 | 340 | img = 'move' if method == 'on_click_l' else 'rotate' |
a6843832 | 341 | if not (img == 'rotate' and not item._instantiated): |
7e487769 | 342 | self._cursor.set_image('assets/images/buttons/%s.dds' % img) |
49c79300 FC |
343 | |
344 | def on_click_l(self): | |
345 | self._on_click('on_click_l') | |
346 | ||
347 | def on_click_r(self): | |
348 | self._on_click('on_click_r') | |
c8d8653f FC |
349 | |
350 | def on_release(self): | |
32aa4dae FC |
351 | if self._item_active and not self._item_active._first_command: |
352 | self._commands = self._commands[:self._command_idx] | |
353 | self._commands += [self._item_active] | |
354 | self._command_idx += 1 | |
f26497a5 FC |
355 | #self.__prev_btn['state'] = NORMAL |
356 | #fcols = (.4, .4, .4, .14), (.3, .3, .3, .05) | |
357 | #self.__prev_btn['frameColor'] = fcols[0] | |
358 | #if self._item_active._command_idx == len(self._item_active._commands) - 1: | |
359 | # self.__next_btn['state'] = DISABLED | |
360 | # self.__next_btn['frameColor'] = fcols[1] | |
7c0a81ae | 361 | self._item_active = None |
49c79300 | 362 | [item.on_release() for item in self.items] |
7e487769 | 363 | self._cursor.set_image('assets/images/buttons/arrowUpLeft.dds') |
37ba71d8 | 364 | |
e1438449 | 365 | def repos(self): |
d5932612 FC |
366 | for item in self.items: |
367 | item.repos_done = False | |
e1438449 | 368 | self.items = sorted(self.items, key=lambda itm: itm.__class__.__name__) |
651713a9 | 369 | [item.on_aspect_ratio_changed() for item in self.items] |
a5dc83f4 | 370 | self._side_panel.update(self.items) |
7790323d | 371 | max_x = -float('inf') |
e1438449 FC |
372 | for item in self.items: |
373 | if not item._instantiated: | |
374 | max_x = max(item._np.get_x(), max_x) | |
375 | for item in self.items: | |
376 | if not item._instantiated: | |
377 | item.repos_x(max_x) | |
378 | ||
379 | def on_aspect_ratio_changed(self): | |
380 | self.repos() | |
651713a9 | 381 | |
0a0994e4 | 382 | def _win_condition(self): |
0e86689f FC |
383 | pass |
384 | ||
0a0994e4 FC |
385 | def _fail_condition(self): |
386 | return all(itm.fail_condition() for itm in self.items) and not self._paused and self._state == 'playing' | |
387 | ||
37ba71d8 | 388 | def on_frame(self, task): |
c8d8653f FC |
389 | hits = self._get_hits() |
390 | pos = None | |
391 | for hit in self._get_hits(): | |
392 | if hit.get_node() == self._mouse_plane_node: | |
393 | pos = hit.get_hit_pos() | |
394 | hit_nodes = [hit.get_node() for hit in hits] | |
7c0a81ae FC |
395 | if self._item_active: |
396 | items_hit = [self._item_active] | |
397 | else: | |
398 | items_hit = [itm for itm in self.items if itm.node in hit_nodes] | |
37ba71d8 FC |
399 | items_no_hit = [itm for itm in self.items if itm not in items_hit] |
400 | [itm.on_mouse_on() for itm in items_hit] | |
401 | [itm.on_mouse_off() for itm in items_no_hit] | |
7c0a81ae FC |
402 | if pos and self._item_active: |
403 | self._item_active.on_mouse_move(pos) | |
31237524 FC |
404 | if self._dbg_items: |
405 | self._update_info(items_hit[0] if items_hit else None) | |
0a0994e4 | 406 | if self._win_condition(): |
ce302b41 | 407 | self._start_evt_time = None |
fa3662a6 | 408 | self._set_fail() if self._enforce_res == 'fail' else self._set_win() |
0a0994e4 | 409 | elif self._state == 'playing' and self._fail_condition(): |
ce302b41 FC |
410 | self._start_evt_time = None |
411 | self._set_win() if self._enforce_res == 'win' else self._set_fail() | |
412 | elif self._testing and self._start_evt_time and globalClock.getFrameTime() - self._start_evt_time > 5.0: | |
413 | self._start_evt_time = None | |
fa3662a6 | 414 | self._set_win() if self._enforce_res == 'win' else self._set_fail() |
93cf86b2 FC |
415 | if any(itm._overlapping for itm in self.items): |
416 | self._cursor.cursor_img.img.set_color(.9, .1, .1, 1) | |
417 | else: | |
418 | self._cursor.cursor_img.img.set_color(.9, .9, .9, 1) | |
37ba71d8 | 419 | return task.cont |
c8d8653f | 420 | |
7850ccc4 FC |
421 | def cb_inst(self, item): |
422 | self.items += [item] | |
423 | ||
c8d8653f | 424 | def on_play(self): |
0a0994e4 | 425 | self._state = 'playing' |
f26497a5 FC |
426 | #self.__prev_btn['state'] = DISABLED |
427 | #self.__next_btn['state'] = DISABLED | |
b41381b2 | 428 | self.__right_btn['state'] = DISABLED |
c8d8653f | 429 | [itm.play() for itm in self.items] |
ce302b41 | 430 | self._start_evt_time = globalClock.getFrameTime() |
36099535 FC |
431 | |
432 | def on_next(self): | |
32aa4dae FC |
433 | self._commands[self._command_idx].redo() |
434 | self._command_idx += 1 | |
c991401b | 435 | #fcols = (.4, .4, .4, .14), (.3, .3, .3, .05) |
f26497a5 FC |
436 | #self.__prev_btn['state'] = NORMAL |
437 | #self.__prev_btn['frameColor'] = fcols[0] | |
c991401b | 438 | #more_commands = self._command_idx < len(self._commands) |
f26497a5 FC |
439 | #self.__next_btn['state'] = NORMAL if more_commands else DISABLED |
440 | #self.__next_btn['frameColor'] = fcols[0] if more_commands else fcols[1] | |
36099535 FC |
441 | |
442 | def on_prev(self): | |
32aa4dae FC |
443 | self._command_idx -= 1 |
444 | self._commands[self._command_idx].undo() | |
c991401b | 445 | #fcols = (.4, .4, .4, .14), (.3, .3, .3, .05) |
f26497a5 FC |
446 | #self.__next_btn['state'] = NORMAL |
447 | #self.__next_btn['frameColor'] = fcols[0] | |
448 | #self.__prev_btn['state'] = NORMAL if self._command_idx else DISABLED | |
449 | #self.__prev_btn['frameColor'] = fcols[0] if self._command_idx else fcols[1] | |
36099535 | 450 | |
36099535 | 451 | def on_home(self): |
5964572b | 452 | self._exit_cb() |
36099535 | 453 | |
2aaa10d3 | 454 | def _set_instructions(self): |
9830561d FC |
455 | self._paused = True |
456 | self.__store_state() | |
2aaa10d3 FC |
457 | mgr = TextPropertiesManager.get_global_ptr() |
458 | for name in ['mouse_l', 'mouse_r']: | |
7e487769 | 459 | graphic = OnscreenImage('assets/images/buttons/%s.dds' % name) |
2aaa10d3 FC |
460 | graphic.set_scale(.5) |
461 | graphic.get_texture().set_minfilter(Texture.FTLinearMipmapLinear) | |
462 | graphic.get_texture().set_anisotropic_degree(2) | |
463 | mgr.set_graphic(name, graphic) | |
464 | graphic.set_z(-.2) | |
465 | graphic.set_transparency(True) | |
466 | graphic.detach_node() | |
467 | frm = DirectFrame(frameColor=(.4, .4, .4, .06), | |
468 | frameSize=(-.6, .6, -.3, .3)) | |
469 | font = base.loader.load_font('assets/fonts/Hanken-Book.ttf') | |
470 | font.clear() | |
471 | font.set_pixels_per_unit(60) | |
472 | font.set_minfilter(Texture.FTLinearMipmapLinear) | |
473 | font.set_outline((0, 0, 0, 1), .8, .2) | |
2aaa10d3 | 474 | self._txt = OnscreenText( |
0eff64a3 FC |
475 | self._instr_txt(), parent=frm, font=font, scale=0.06, |
476 | fg=(.9, .9, .9, 1), align=TextNode.A_left) | |
2aaa10d3 FC |
477 | u_l = self._txt.textNode.get_upper_left_3d() |
478 | l_r = self._txt.textNode.get_lower_right_3d() | |
479 | w, h = l_r[0] - u_l[0], u_l[2] - l_r[2] | |
a0acba9a FC |
480 | btn_scale = .05 |
481 | mar = .06 # margin | |
2aaa10d3 | 482 | z = h / 2 - font.get_line_height() * self._txt['scale'][1] |
a0acba9a | 483 | z += (btn_scale + 2 * mar) / 2 |
2aaa10d3 FC |
484 | self._txt['pos'] = -w / 2, z |
485 | u_l = self._txt.textNode.get_upper_left_3d() | |
486 | l_r = self._txt.textNode.get_lower_right_3d() | |
a0acba9a FC |
487 | c_l_r = l_r[0], l_r[1], l_r[2] - 2 * mar - btn_scale |
488 | fsz = u_l[0] - mar, l_r[0] + mar, c_l_r[2] - mar, u_l[2] + mar | |
2aaa10d3 | 489 | frm['frameSize'] = fsz |
a0acba9a FC |
490 | colors = [ |
491 | (.6, .6, .6, 1), # ready | |
492 | (1, 1, 1, 1), # press | |
493 | (.8, .8, .8, 1), # rollover | |
494 | (.4, .4, .4, .4)] | |
495 | imgs = [self.__load_img_btn('exitRight', col) for col in colors] | |
496 | btn = DirectButton( | |
497 | image=imgs, scale=btn_scale, | |
498 | pos=(l_r[0] - btn_scale, 1, l_r[2] - mar - btn_scale), | |
499 | parent=frm, command=self.__on_close_instructions, extraArgs=[frm], | |
500 | relief=FLAT, frameColor=(.6, .6, .6, .08), | |
501 | rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'), | |
502 | clickSound=loader.load_sfx('assets/audio/sfx/click.ogg')) | |
503 | btn.set_transparency(True) | |
2d1773b1 | 504 | self._pos_mgr.register('close_instructions', LibP3d.wdg_pos(btn)) |
a0acba9a | 505 | |
0a0994e4 | 506 | def _set_win(self): |
3fe18d73 | 507 | self.__persistent.save_scene(self.__class__.__name__, self.version()) |
9914cfc9 FC |
508 | loader.load_sfx('assets/audio/sfx/success.ogg').play() |
509 | self._paused = True | |
510 | self.__store_state() | |
511 | frm = DirectFrame(frameColor=(.4, .4, .4, .06), | |
512 | frameSize=(-.6, .6, -.3, .3)) | |
513 | font = base.loader.load_font('assets/fonts/Hanken-Book.ttf') | |
514 | font.clear() | |
515 | font.set_pixels_per_unit(60) | |
516 | font.set_minfilter(Texture.FTLinearMipmapLinear) | |
517 | font.set_outline((0, 0, 0, 1), .8, .2) | |
518 | self._txt = OnscreenText( | |
519 | _('You win!'), | |
520 | parent=frm, | |
521 | font=font, scale=0.2, | |
522 | fg=(.9, .9, .9, 1)) | |
523 | u_l = self._txt.textNode.get_upper_left_3d() | |
524 | l_r = self._txt.textNode.get_lower_right_3d() | |
c991401b FC |
525 | #w, h = l_r[0] - u_l[0], u_l[2] - l_r[2] |
526 | h = u_l[2] - l_r[2] | |
9914cfc9 FC |
527 | btn_scale = .05 |
528 | mar = .06 # margin | |
529 | z = h / 2 - font.get_line_height() * self._txt['scale'][1] | |
530 | z += (btn_scale + 2 * mar) / 2 | |
531 | self._txt['pos'] = 0, z | |
532 | u_l = self._txt.textNode.get_upper_left_3d() | |
533 | l_r = self._txt.textNode.get_lower_right_3d() | |
534 | c_l_r = l_r[0], l_r[1], l_r[2] - 2 * mar - btn_scale | |
535 | fsz = u_l[0] - mar, l_r[0] + mar, c_l_r[2] - mar, u_l[2] + mar | |
536 | frm['frameSize'] = fsz | |
537 | colors = [ | |
538 | (.6, .6, .6, 1), # ready | |
539 | (1, 1, 1, 1), # press | |
540 | (.8, .8, .8, 1), # rollover | |
541 | (.4, .4, .4, .4)] | |
542 | imgs = [self.__load_img_btn('home', col) for col in colors] | |
543 | btn = DirectButton( | |
544 | image=imgs, scale=btn_scale, | |
545 | pos=(-2.8 * btn_scale, 1, l_r[2] - mar - btn_scale), | |
546 | parent=frm, command=self._on_end_home, extraArgs=[frm], | |
547 | relief=FLAT, frameColor=(.6, .6, .6, .08), | |
548 | rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'), | |
549 | clickSound=loader.load_sfx('assets/audio/sfx/click.ogg')) | |
550 | btn.set_transparency(True) | |
2d1773b1 | 551 | self._pos_mgr.register('home_win', LibP3d.wdg_pos(btn)) |
9914cfc9 FC |
552 | imgs = [self.__load_img_btn('rewind', col) for col in colors] |
553 | btn = DirectButton( | |
554 | image=imgs, scale=btn_scale, | |
555 | pos=(0, 1, l_r[2] - mar - btn_scale), | |
556 | parent=frm, command=self._on_restart, extraArgs=[frm], | |
557 | relief=FLAT, frameColor=(.6, .6, .6, .08), | |
558 | rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'), | |
559 | clickSound=loader.load_sfx('assets/audio/sfx/click.ogg')) | |
2d1773b1 | 560 | self._pos_mgr.register('replay', LibP3d.wdg_pos(btn)) |
9914cfc9 | 561 | btn.set_transparency(True) |
6168d0c2 | 562 | enabled = self._scenes.index(self.__class__) < len(self._scenes) - 1 |
9914cfc9 | 563 | if enabled: |
6168d0c2 | 564 | next_scene = self._scenes[self._scenes.index(self.__class__) + 1] |
9914cfc9 FC |
565 | else: |
566 | next_scene = None | |
567 | imgs = [self.__load_img_btn('right', col) for col in colors] | |
568 | btn = DirectButton( | |
569 | image=imgs, scale=btn_scale, | |
570 | pos=(2.8 * btn_scale, 1, l_r[2] - mar - btn_scale), | |
571 | parent=frm, command=self._on_next_scene, | |
572 | extraArgs=[frm, next_scene], relief=FLAT, | |
573 | frameColor=(.6, .6, .6, .08), | |
574 | rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'), | |
575 | clickSound=loader.load_sfx('assets/audio/sfx/click.ogg')) | |
576 | btn['state'] = NORMAL if enabled else DISABLED | |
2d1773b1 | 577 | self._pos_mgr.register('next', LibP3d.wdg_pos(btn)) |
9914cfc9 FC |
578 | btn.set_transparency(True) |
579 | ||
0a0994e4 FC |
580 | def _set_fail(self): |
581 | loader.load_sfx('assets/audio/sfx/success.ogg').play() | |
582 | self._paused = True | |
583 | self.__store_state() | |
584 | frm = DirectFrame(frameColor=(.4, .4, .4, .06), | |
585 | frameSize=(-.6, .6, -.3, .3)) | |
586 | font = base.loader.load_font('assets/fonts/Hanken-Book.ttf') | |
587 | font.clear() | |
588 | font.set_pixels_per_unit(60) | |
589 | font.set_minfilter(Texture.FTLinearMipmapLinear) | |
590 | font.set_outline((0, 0, 0, 1), .8, .2) | |
591 | self._txt = OnscreenText( | |
592 | _('You have failed!'), | |
593 | parent=frm, | |
594 | font=font, scale=0.2, | |
595 | fg=(.9, .9, .9, 1)) | |
596 | u_l = self._txt.textNode.get_upper_left_3d() | |
597 | l_r = self._txt.textNode.get_lower_right_3d() | |
c991401b FC |
598 | #w, h = l_r[0] - u_l[0], u_l[2] - l_r[2] |
599 | h = u_l[2] - l_r[2] | |
0a0994e4 FC |
600 | btn_scale = .05 |
601 | mar = .06 # margin | |
602 | z = h / 2 - font.get_line_height() * self._txt['scale'][1] | |
603 | z += (btn_scale + 2 * mar) / 2 | |
604 | self._txt['pos'] = 0, z | |
605 | u_l = self._txt.textNode.get_upper_left_3d() | |
606 | l_r = self._txt.textNode.get_lower_right_3d() | |
607 | c_l_r = l_r[0], l_r[1], l_r[2] - 2 * mar - btn_scale | |
608 | fsz = u_l[0] - mar, l_r[0] + mar, c_l_r[2] - mar, u_l[2] + mar | |
609 | frm['frameSize'] = fsz | |
610 | colors = [ | |
611 | (.6, .6, .6, 1), # ready | |
612 | (1, 1, 1, 1), # press | |
613 | (.8, .8, .8, 1), # rollover | |
614 | (.4, .4, .4, .4)] | |
615 | imgs = [self.__load_img_btn('home', col) for col in colors] | |
616 | btn = DirectButton( | |
617 | image=imgs, scale=btn_scale, | |
618 | pos=(-2.8 * btn_scale, 1, l_r[2] - mar - btn_scale), | |
619 | parent=frm, command=self._on_end_home, extraArgs=[frm], | |
620 | relief=FLAT, frameColor=(.6, .6, .6, .08), | |
621 | rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'), | |
622 | clickSound=loader.load_sfx('assets/audio/sfx/click.ogg')) | |
2d1773b1 | 623 | self._pos_mgr.register('home_win', LibP3d.wdg_pos(btn)) |
0a0994e4 FC |
624 | btn.set_transparency(True) |
625 | imgs = [self.__load_img_btn('rewind', col) for col in colors] | |
626 | btn = DirectButton( | |
627 | image=imgs, scale=btn_scale, | |
628 | pos=(0, 1, l_r[2] - mar - btn_scale), | |
629 | parent=frm, command=self._on_restart, extraArgs=[frm], | |
630 | relief=FLAT, frameColor=(.6, .6, .6, .08), | |
631 | rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'), | |
632 | clickSound=loader.load_sfx('assets/audio/sfx/click.ogg')) | |
2d1773b1 | 633 | self._pos_mgr.register('replay', LibP3d.wdg_pos(btn)) |
0a0994e4 FC |
634 | btn.set_transparency(True) |
635 | ||
9914cfc9 FC |
636 | def _on_restart(self, frm): |
637 | self.__on_close_instructions(frm) | |
638 | self.reset() | |
639 | ||
640 | def _on_end_home(self, frm): | |
641 | self.__on_close_instructions(frm) | |
642 | self.on_home() | |
643 | ||
644 | def _on_next_scene(self, frm, scene): | |
645 | self.__on_close_instructions(frm) | |
646 | self._reload_cb(scene) | |
647 | ||
a0acba9a FC |
648 | def __store_state(self): |
649 | btns = [ | |
650 | self.__home_btn, self.__info_btn, self.__right_btn, | |
f26497a5 FC |
651 | #self.__next_btn, self.__prev_btn, self.__rewind_btn |
652 | ] | |
a0acba9a FC |
653 | self.__btn_state = [btn['state'] for btn in btns] |
654 | for btn in btns: | |
655 | btn['state'] = DISABLED | |
656 | [itm.store_state() for itm in self.items] | |
657 | ||
658 | def __restore_state(self): | |
659 | btns = [ | |
660 | self.__home_btn, self.__info_btn, self.__right_btn, | |
f26497a5 FC |
661 | #self.__next_btn, self.__prev_btn, self.__rewind_btn |
662 | ] | |
a0acba9a FC |
663 | for btn, state in zip(btns, self.__btn_state): |
664 | btn['state'] = state | |
665 | [itm.restore_state() for itm in self.items] | |
666 | self._paused = False | |
667 | ||
668 | def __on_close_instructions(self, frm): | |
669 | frm.remove_node() | |
670 | self.__restore_state() | |
067a36db FC |
671 | |
672 | def _set_test_items(self): | |
673 | def frame_after(task): | |
674 | self._define_test_items() | |
675 | for itm in self._test_items: | |
676 | self._pos_mgr.register(itm.name, P3dGfxMgr.pos2d_p2d(itm)) | |
677 | taskMgr.doMethodLater(.01, frame_after, 'frame after') | |
678 | ||
679 | def _set_test_item(self, name, pos): | |
680 | self._test_items += [NodePath(name)] | |
681 | self._test_items[-1].set_pos(pos[0], 0, pos[1]) |