-from panda3d.core import CullFaceAttrib
+from panda3d.core import CullFaceAttrib, Point3, NodePath, Point2, Texture
from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode
+from direct.gui.OnscreenText import OnscreenText
+from lib.lib.p3d.gfx import P3dGfxMgr
class Box:
- def __init__(self, world):
+ def __init__(self, world, plane_node, count, cb_inst):
+ self._world = world
+ self._plane_node = plane_node
+ self._count = count
+ self._cb_inst = cb_inst
shape = BulletBoxShape((.5, .5, .5))
self.node = BulletRigidBodyNode('box')
- # self.node.set_mass(1) # static/dynamic
self.node.add_shape(shape)
- np = render.attach_new_node(self.node)
- np.set_pos(0, 0, 1)
+ self._np = render.attach_new_node(self.node)
world.attach_rigid_body(self.node)
model = loader.load_model('assets/gltf/box/box.gltf')
model.flatten_light()
- model.reparent_to(np)
- self._set_outline_model(np)
+ model.reparent_to(self._np)
+ self._set_outline_model()
+ self._start_drag_pos = None
+ self._prev_rot_info = None
+ self._instantiated = False
+ taskMgr.add(self.on_frame, 'on_frame')
+ self._repos()
- def _set_outline_model(self, np):
+ def _repos(self):
+ p_from, p_to = P3dGfxMgr.world_from_to((-1, 1))
+ for hit in self._world.ray_test_all(p_from, p_to).get_hits():
+ if hit.get_node() == self._plane_node:
+ pos = hit.get_hit_pos()
+ corner = P3dGfxMgr.screen_coord(pos)
+ bounds = self._np.get_tight_bounds()
+ bounds = bounds[0] - self._np.get_pos(), bounds[1] - self._np.get_pos()
+ self._np.set_pos(pos)
+ dist = -1, -1
+ def __update(set, get, delta):
+ set(get() + delta)
+ top_left = self._np.get_pos() + (bounds[0][0], bounds[0][1], bounds[1][2])
+ tl2d = P3dGfxMgr.screen_coord(top_left)
+ tmpnode = NodePath('tmp')
+ tmpnode.set_pos(tl2d[0], 0, tl2d[1])
+ cornernode = NodePath('corner')
+ cornernode.set_pos(corner[0], 0, corner[1])
+ dist = tmpnode.get_pos(cornernode)
+ tmpnode.remove_node()
+ cornernode.remove_node()
+ return dist
+ while dist[0] < .01:
+ dist = __update(self._np.set_x, self._np.get_x, .01)
+ while dist[2] > -.01:
+ dist = __update(self._np.set_z, self._np.get_z, -.01)
+ if not hasattr(self, '_txt'):
+ font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
+ font.clear()
+ font.set_pixels_per_unit(60)
+ font.set_minfilter(Texture.FTLinearMipmapLinear)
+ font.set_outline((0, 0, 0, 1), .8, .2)
+ self._txt = OnscreenText(
+ str(self._count), font=font, scale=0.06, fg=(.9, .9, .9, 1))
+ pos = self._np.get_pos() + (bounds[1][0], bounds[0][1], bounds[0][2])
+ p2d = P3dGfxMgr.screen_coord(pos)
+ self._txt['pos'] = p2d
+
+ def get_corner(self):
+ bounds = self._np.get_tight_bounds()
+ return bounds[1][0], bounds[1][1], bounds[0][2]
+
+ def _set_outline_model(self):
self._outline_model = loader.load_model('assets/gltf/box/box.gltf')
clockw = CullFaceAttrib.MCullClockwise
self._outline_model.set_attrib(CullFaceAttrib.make(clockw))
- self._outline_model.reparent_to(np)
+ self._outline_model.reparent_to(self._np)
self._outline_model.set_scale(-1.08, -1.08, -1.08)
self._outline_model.set_light_off()
self._outline_model.set_color(.4, .4, .4, 1)
self._outline_model.set_color_scale(.4, .4, .4, 1)
self._outline_model.hide()
- def on_click(self, hit):
- print(hit.get_hit_pos())
+ def on_frame(self, task):
+ self._np.set_y(0)
+ return task.cont
+
+ def play(self):
+ self._world.remove_rigid_body(self.node)
+ self.node.set_mass(1)
+ self._world.attach_rigid_body(self.node)
+
+ def on_click_l(self, pos):
+ self._start_drag_pos = pos, self._np.get_pos()
+ loader.load_sfx('assets/audio/sfx/grab.ogg').play()
+ if not self._instantiated:
+ self._instantiated = True
+ self._txt.destroy()
+ self._count -= 1
+ if self._count:
+ box = Box(self._world, self._plane_node, self._count, self._cb_inst)
+ self._cb_inst(box)
+
+ def on_click_r(self, pos):
+ self._prev_rot_info = pos, self._np.get_pos(), self._np.get_r()
+ loader.load_sfx('assets/audio/sfx/grab.ogg').play()
+
+ def on_release(self):
+ if self._start_drag_pos or self._prev_rot_info:
+ loader.load_sfx('assets/audio/sfx/release.ogg').play()
+ self._start_drag_pos = self._prev_rot_info = None
def on_mouse_on(self):
self._outline_model.show()
def on_mouse_off(self):
+ if self._start_drag_pos or self._prev_rot_info: return
self._outline_model.hide()
+
+ def on_mouse_move(self, pos):
+ if self._start_drag_pos:
+ d_pos = pos - self._start_drag_pos[0]
+ self._np.set_pos(self._start_drag_pos[1] + d_pos)
+ if self._prev_rot_info:
+ start_vec = self._prev_rot_info[0] - self._prev_rot_info[1]
+ curr_vec = pos - self._prev_rot_info[1]
+ d_angle = curr_vec.signed_angle_deg(start_vec, (0, -1, 0))
+ self._np.set_r(self._prev_rot_info[2] + d_angle)
+ self._prev_rot_info = pos, self._np.get_pos(), self._np.get_r()
+
+ def on_aspect_ratio_changed(self):
+ if not self._instantiated:
+ self._repos()