1 from panda3d
.core
import CullFaceAttrib
, Point3
, NodePath
, Point2
, Texture
2 from panda3d
.bullet
import BulletBoxShape
, BulletRigidBodyNode
3 from direct
.gui
.OnscreenText
import OnscreenText
8 def __init__(self
, world
, plane_node
, count
, cb_inst
):
10 self
._plane
_node
= plane_node
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')
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')
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
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
)
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')
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()
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()
70 def on_frame(self
, task
):
75 self
._world
.remove_rigid_body(self
.node
)
77 self
._world
.attach_rigid_body(self
.node
)
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
87 box
= Box(self
._world
, self
._plane
_node
, self
._count
, self
._cb
_inst
)
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()
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
99 def on_mouse_on(self
):
100 self
._outline
_model
.show()
102 def on_mouse_off(self
):
103 if self
._start
_drag
_pos
or self
._prev
_rot
_info
: return
104 self
._outline
_model
.hide()
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()