| 1 | from panda3d.core import CullFaceAttrib |
| 2 | from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode |
| 3 | |
| 4 | class Box: |
| 5 | |
| 6 | def __init__(self, world): |
| 7 | self._world = world |
| 8 | shape = BulletBoxShape((.5, .5, .5)) |
| 9 | self.node = BulletRigidBodyNode('box') |
| 10 | self.node.add_shape(shape) |
| 11 | self._np = render.attach_new_node(self.node) |
| 12 | self._np.set_pos(0, 0, 1) |
| 13 | world.attach_rigid_body(self.node) |
| 14 | model = loader.load_model('assets/gltf/box/box.gltf') |
| 15 | model.flatten_light() |
| 16 | model.reparent_to(self._np) |
| 17 | self._set_outline_model() |
| 18 | self._start_drag_pos = None |
| 19 | self._start_rot_info = None |
| 20 | taskMgr.add(self.on_frame, 'on_frame') |
| 21 | |
| 22 | def _set_outline_model(self): |
| 23 | self._outline_model = loader.load_model('assets/gltf/box/box.gltf') |
| 24 | clockw = CullFaceAttrib.MCullClockwise |
| 25 | self._outline_model.set_attrib(CullFaceAttrib.make(clockw)) |
| 26 | self._outline_model.reparent_to(self._np) |
| 27 | self._outline_model.set_scale(-1.08, -1.08, -1.08) |
| 28 | self._outline_model.set_light_off() |
| 29 | self._outline_model.set_color(.4, .4, .4, 1) |
| 30 | self._outline_model.set_color_scale(.4, .4, .4, 1) |
| 31 | self._outline_model.hide() |
| 32 | |
| 33 | def on_frame(self, task): |
| 34 | self._np.set_y(0) |
| 35 | return task.cont |
| 36 | |
| 37 | def play(self): |
| 38 | self._world.remove_rigid_body(self.node) |
| 39 | self.node.set_mass(1) |
| 40 | self._world.attach_rigid_body(self.node) |
| 41 | |
| 42 | def on_click_l(self, pos): |
| 43 | self._start_drag_pos = pos, self._np.get_pos() |
| 44 | loader.load_sfx('assets/audio/sfx/grab.ogg').play() |
| 45 | |
| 46 | def on_click_r(self, pos): |
| 47 | self._start_rot_info = pos, self._np.get_pos(), self._np.get_r() |
| 48 | loader.load_sfx('assets/audio/sfx/grab.ogg').play() |
| 49 | |
| 50 | def on_release(self): |
| 51 | if self._start_drag_pos or self._start_rot_info: |
| 52 | loader.load_sfx('assets/audio/sfx/release.ogg').play() |
| 53 | self._start_drag_pos = self._start_rot_info = None |
| 54 | |
| 55 | def on_mouse_on(self): |
| 56 | self._outline_model.show() |
| 57 | |
| 58 | def on_mouse_off(self): |
| 59 | if self._start_drag_pos or self._start_rot_info: return |
| 60 | self._outline_model.hide() |
| 61 | |
| 62 | def on_mouse_move(self, pos): |
| 63 | if self._start_drag_pos: |
| 64 | d_pos = pos - self._start_drag_pos[0] |
| 65 | self._np.set_pos(self._start_drag_pos[1] + d_pos) |
| 66 | if self._start_rot_info: |
| 67 | start_vec = self._start_rot_info[0] - self._start_rot_info[1] |
| 68 | curr_vec = pos - self._start_rot_info[1] |
| 69 | d_angle = curr_vec.signed_angle_deg(start_vec, (0, -1, 0)) |
| 70 | self._np.set_r(self._start_rot_info[2] + d_angle) |