929756db62e40afa07b62f7037bfcf47b16df958
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')
29 p_from
, p_to
= Point3(), Point3() # in camera coordinates
30 base
.camLens
.extrude((-1, 1), p_from
, p_to
)
31 p_from
= render
.get_relative_point(base
.cam
, p_from
) # global coords
32 p_to
= render
.get_relative_point(base
.cam
, p_to
) # global coords
33 for hit
in self
._world
.ray_test_all(p_from
, p_to
).get_hits():
34 if hit
.get_node() == self
._plane
_node
:
35 pos
= hit
.get_hit_pos()
36 bounds
= self
._np
.get_tight_bounds()
37 bounds
= bounds
[0] - self
._np
.get_pos(), bounds
[1] - self
._np
.get_pos()
39 dpos
= bounds
[1][0] + margin
[0], 0, -bounds
[1][2] - margin
[1]
40 self
._np
.set_pos(pos
+ dpos
)
41 new_node
= NodePath('temp')
42 new_node
.set_pos(pos
+ dpos
+ (bounds
[1][0], bounds
[1][1], -bounds
[1][2]))
43 coord3d
= new_node
.get_pos(base
.cam
)
45 base
.camLens
.project(coord3d
, coord2d
)
46 coord_r2d
= Point3(coord2d
[0], 0, coord2d
[1])
47 coord_a2d
= base
.aspect2d
.get_relative_point(render2d
, coord_r2d
)
48 if not hasattr(self
, '_txt'):
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
), font
=font
, scale
=0.06, fg
=(.9, .9, .9, 1))
56 self
._txt
['pos'] = coord_a2d
[0], coord_a2d
[2]
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()
117 def on_aspect_ratio_changed(self
):
118 if not self
._instantiated
: