1 from logging
import info
2 from lib
.gameobject
import Colleague
3 from lib
.lib
.bullet
.bullet
import (
4 BulletPhysWorld
, BulletTriangleMesh
, BulletTriangleMeshShape
,
5 BulletRigidBodyNode
, BulletGhostNode
)
8 PhysWorld
= BulletPhysWorld
9 TriangleMesh
= BulletTriangleMesh
10 TriangleMeshShape
= BulletTriangleMeshShape
11 RigidBodyNode
= BulletRigidBodyNode
12 GhostNode
= BulletGhostNode
17 def __init__(self
, node
, time
):
24 def attach_rigid_body(self
, rbnode
):
25 return self
.root
.attach_rigid_body(rbnode
)
27 def remove_rigid_body(self
, rbnode
):
28 return self
.root
.remove_rigid_body(rbnode
)
30 def attach_ghost(self
, gnode
): return self
.root
.attach_ghost(gnode
)
31 def remove_ghost(self
, gnode
): return self
.root
.remove_ghost(gnode
)
32 def attach_vehicle(self
, vehicle
): return self
.root
.attach_vehicle(vehicle
)
33 def remove_vehicle(self
, vehicle
): return self
.root
.remove_vehicle(vehicle
)
35 def ray_test_all(self
, from_pos
, to_pos
, mask
=None):
36 return self
.root
.ray_test_all(from_pos
, to_pos
, mask
)
38 def ray_test_closest(self
, from_pos
, to_pos
, mask
=None):
39 return self
.root
.ray_test_closest(from_pos
, to_pos
, mask
)
42 class PhysMgr(Colleague
, PhysFacade
):
44 def __init__(self
, mediator
):
45 Colleague
.__init
__(self
, mediator
)
46 self
.collision_objs
= [] # objects to be processed
47 self
.__obj
2coll
= {} # {obj: [(node, coll_time), ...], ...}
49 self
.__debug
_np
= None
50 PhysFacade
.__init
__(self
)
53 self
.collision_objs
= []
55 self
.root
= PhysWorld()
56 self
.root
.set_gravity((0, 0, -8.5))
57 self
.root
.init_debug()
60 self
.eng
.attach_obs(self
.on_frame
, 2)
63 self
.root
.do_phys(self
.eng
.lib
.last_frame_dt
, 10, 1/180.0)
64 self
.__do
_collisions
()
66 def ray_test_closest(self
, top
, bottom
):
67 #TODO: differs from PhysFacade's signature
68 return self
.root
.ray_test_closest(top
, bottom
)
70 def add_collision_obj(self
, node
): self
.collision_objs
+= [node
]
72 def remove_collision_obj(self
, node
):
73 try: self
.collision_objs
.remove(node
)
75 info("can't remove collision object %s" % node
)
76 # it may happen with weapons during pause
81 self
.eng
.detach_obs(self
.on_frame
)
83 def __do_collisions(self
):
84 to_clear
= self
.collision_objs
[:]
85 # identical collisions are ignored for .25 seconds
86 for obj
in self
.collision_objs
:
87 if obj
not in self
.__obj
2coll
: self
.__obj
2coll
[obj
] = []
88 # for contact in self.root.get_contacts(obj):
89 # this doesn't work in 1.9, the following works
90 # odd, this doesn't work too
91 # for contact in self.root.wld.contact_test(obj).get_contacts():
92 result
= self
.root
._wld
.contact_test(obj
)
93 #TODO: access a protected member
94 for contact
in result
.get_contacts():
95 self
.__process
_contact
(obj
, contact
.get_node0(), to_clear
)
96 self
.__process
_contact
(obj
, contact
.get_node1(), to_clear
)
98 if obj
in self
.__obj
2coll
: # it may be that it isn't here e.g.
99 # when you fire a rocket while you're very close to the prev
100 # car and the rocket is removed suddenly
101 for coll
in self
.__obj
2coll
[obj
]:
102 if self
.eng
.curr_time
- coll
.time
> .25:
103 self
.__obj
2coll
[obj
].remove(coll
)
105 def __process_contact(self
, obj
, node
, to_clear
):
106 if node
== obj
: return
107 if obj
in to_clear
: to_clear
.remove(obj
)
108 if node
in [coll
.node
for coll
in self
.__obj
2coll
[obj
]]: return
109 self
.__obj
2coll
[obj
] += [CollInfo(node
, self
.eng
.curr_time
)]
110 self
.eng
.event
.notify('on_collision', obj
, node
)
112 def toggle_dbg(self
):
113 if self
.root
: self
.root
.toggle_dbg()