ya2 · news · projects · code · about

493ae2a26766d046a5df3d773c1e7b5eb7ff7120
[pmachines.git] / pmachines / items / box.py
1 from panda3d.core import CullFaceAttrib, Point3, NodePath, Point2, Texture
2 from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode
3 from direct.gui.OnscreenText import OnscreenText
4
5
6 class Box:
7
8 def __init__(self, world, plane_node, count, cb_inst):
9 self._world = world
10 self._plane_node = plane_node
11 self._count = count
12 self._cb_inst = cb_inst
13 shape = BulletBoxShape((.5, .5, .5))
14 self.node = BulletRigidBodyNode('box')
15 self.node.add_shape(shape)
16 self._np = render.attach_new_node(self.node)
17 world.attach_rigid_body(self.node)
18 model = loader.load_model('assets/gltf/box/box.gltf')
19 model.flatten_light()
20 model.reparent_to(self._np)
21 self._set_outline_model()
22 self._start_drag_pos = None
23 self._prev_rot_info = None
24 self._instantiated = False
25 taskMgr.add(self.on_frame, 'on_frame')
26 #self._set_side()
27 taskMgr.doMethodLater(.01, lambda task: self._set_side(), 'a')
28 # i get weird values in the first frame; i could restore this approach
29 # when the hook with the events of the window is up
30
31 def _set_side(self):
32 p_from, p_to = Point3(), Point3() # in camera coordinates
33 base.camLens.extrude((-1, 1), p_from, p_to)
34 p_from = render.get_relative_point(base.cam, p_from) # global coords
35 p_to = render.get_relative_point(base.cam, p_to) # global coords
36 for hit in self._world.ray_test_all(p_from, p_to).get_hits():
37 if hit.get_node() == self._plane_node:
38 pos = hit.get_hit_pos()
39 bounds = self._np.get_tight_bounds()
40 dpos = bounds[1][0], 0, -bounds[1][2]
41 self._np.set_pos(pos + dpos)
42 new_node = NodePath('temp')
43 new_node.set_pos(pos + dpos + (bounds[1][0], bounds[1][1], -bounds[1][2]))
44 coord3d = new_node.get_pos(base.cam)
45 coord2d = Point2()
46 base.camLens.project(coord3d, coord2d)
47 coord_r2d = Point3(coord2d[0], 0, coord2d[1])
48 coord_a2d = base.aspect2d.get_relative_point(render2d, coord_r2d)
49 font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
50 font.clear()
51 font.set_pixels_per_unit(60)
52 font.set_minfilter(Texture.FTLinearMipmapLinear)
53 font.set_outline((0, 0, 0, 1), .8, .2)
54 self._txt = OnscreenText(
55 str(self._count), pos=(coord_a2d[0], coord_a2d[2]),
56 font=font, scale=0.06, fg=(.9, .9, .9, 1))
57 new_node.remove_node()
58
59 def _set_outline_model(self):
60 self._outline_model = loader.load_model('assets/gltf/box/box.gltf')
61 clockw = CullFaceAttrib.MCullClockwise
62 self._outline_model.set_attrib(CullFaceAttrib.make(clockw))
63 self._outline_model.reparent_to(self._np)
64 self._outline_model.set_scale(-1.08, -1.08, -1.08)
65 self._outline_model.set_light_off()
66 self._outline_model.set_color(.4, .4, .4, 1)
67 self._outline_model.set_color_scale(.4, .4, .4, 1)
68 self._outline_model.hide()
69
70 def on_frame(self, task):
71 self._np.set_y(0)
72 return task.cont
73
74 def play(self):
75 self._world.remove_rigid_body(self.node)
76 self.node.set_mass(1)
77 self._world.attach_rigid_body(self.node)
78
79 def on_click_l(self, pos):
80 self._start_drag_pos = pos, self._np.get_pos()
81 loader.load_sfx('assets/audio/sfx/grab.ogg').play()
82 if not self._instantiated:
83 self._instantiated = True
84 self._txt.destroy()
85 self._count -= 1
86 if self._count:
87 box = Box(self._world, self._plane_node, self._count, self._cb_inst)
88 self._cb_inst(box)
89
90 def on_click_r(self, pos):
91 self._prev_rot_info = pos, self._np.get_pos(), self._np.get_r()
92 loader.load_sfx('assets/audio/sfx/grab.ogg').play()
93
94 def on_release(self):
95 if self._start_drag_pos or self._prev_rot_info:
96 loader.load_sfx('assets/audio/sfx/release.ogg').play()
97 self._start_drag_pos = self._prev_rot_info = None
98
99 def on_mouse_on(self):
100 self._outline_model.show()
101
102 def on_mouse_off(self):
103 if self._start_drag_pos or self._prev_rot_info: return
104 self._outline_model.hide()
105
106 def on_mouse_move(self, pos):
107 if self._start_drag_pos:
108 d_pos = pos - self._start_drag_pos[0]
109 self._np.set_pos(self._start_drag_pos[1] + d_pos)
110 if self._prev_rot_info:
111 start_vec = self._prev_rot_info[0] - self._prev_rot_info[1]
112 curr_vec = pos - self._prev_rot_info[1]
113 d_angle = curr_vec.signed_angle_deg(start_vec, (0, -1, 0))
114 self._np.set_r(self._prev_rot_info[2] + d_angle)
115 self._prev_rot_info = pos, self._np.get_pos(), self._np.get_r()