Box2D/Box2D_contact.i (246 lines of code) (raw):

/* * pybox2d -- http://pybox2d.googlecode.com * * Copyright (c) 2010 Ken Lauer / sirkne at gmail dot com * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ /**** b2GetPointStates ****/ %inline { PyObject* b2GetPointStates(const b2Manifold* manifold1, const b2Manifold* manifold2) { PyObject* ret=NULL; b2PointState state1[b2_maxManifoldPoints], state2[b2_maxManifoldPoints]; if (!manifold1 || !manifold2) return NULL; b2GetPointStates(state1, state2, manifold1, manifold2); ret = PyTuple_New(2); int state1_length=-1, state2_length=-1; PyObject* state1_t=Py_None; PyObject* state2_t=Py_None; for (int i=0; i < b2_maxManifoldPoints; i++) { if (state1[i]==b2_nullState && state1_length==0) state1_length=i; if (state2_length > -1) break; if (state2[i]==b2_nullState && state2_length==0) state2_length=i; if (state1_length > -1) break; } if (state1_length < 0) state1_length = b2_maxManifoldPoints; if (state2_length < 0) state2_length = b2_maxManifoldPoints; if (state1_length > -1) state1_t=PyTuple_New(state1_length); else Py_INCREF(state1_t); if (state2_length > -1) state2_t=PyTuple_New(state2_length); else Py_INCREF(state2_t); PyTuple_SetItem(ret, 0, state1_t); PyTuple_SetItem(ret, 1, state2_t); for (int i=0; i < b2Max(state1_length, state2_length); i++) { if (i < state1_length) PyTuple_SetItem(state1_t, i, SWIG_From_int(state1[i])); if (i < state2_length) PyTuple_SetItem(state2_t, i, SWIG_From_int(state2[i])); } return ret; } } %ignore b2GetPointStates; /**** Manifold ****/ %rename (type_) b2Manifold::type; %ignore b2Manifold::points; %extend b2Manifold { public: %pythoncode %{ def __GetPoints(self): return [self.__GetPoint(i) for i in range(self.pointCount)] points = property(__GetPoints, None) %} b2ManifoldPoint* __GetPoint(int i) { if (i >= b2_maxManifoldPoints || i >= $self->pointCount) return NULL; return &( $self->points[i] ); } } /**** ContactManager ****/ %rename(broadPhase) b2ContactManager::m_broadPhase; %rename(contactList) b2ContactManager::m_contactList; %rename(contactCount) b2ContactManager::m_contactCount; %rename(contactFilter) b2ContactManager::m_contactFilter; %rename(contactListener) b2ContactManager::m_contactListener; %rename(allocator) b2ContactManager::m_allocator; %extend b2ContactManager { public: // TODO contact lists, etc. same as b2World %pythoncode %{ %} } /* ContactImpulse */ %extend b2ContactImpulse { public: PyObject* __get_normal_impulses() { PyObject* ret = PyTuple_New($self->count); for (int i=0; i < $self->count; i++) PyTuple_SetItem(ret, i, SWIG_From_double((float32)($self->normalImpulses[i]))); return ret; } PyObject* __get_tangent_impulses() { PyObject* ret = PyTuple_New($self->count); for (int i=0; i < $self->count; i++) PyTuple_SetItem(ret, i, SWIG_From_double((float32)($self->tangentImpulses[i]))); return ret; } %pythoncode %{ normalImpulses = property(__get_normal_impulses, None) tangentImpulses = property(__get_tangent_impulses, None) %} } %ignore b2ContactImpulse::normalImpulses; %ignore b2ContactImpulse::tangentImpulses; /**** WorldManifold ****/ %ignore b2WorldManifold::points; %extend b2WorldManifold { public: %pythoncode %{ %} PyObject* __get_points() { PyObject* ret=PyTuple_New(b2_maxManifoldPoints); PyObject* point; for (int i=0; i < b2_maxManifoldPoints; i++) { point = PyTuple_New(2); PyTuple_SetItem(point, 0, SWIG_From_double((float32)$self->points[i].x)); PyTuple_SetItem(point, 1, SWIG_From_double((float32)$self->points[i].y)); PyTuple_SetItem(ret, i, point); } return ret; } %pythoncode %{ points = property(__get_points, None) %} } /**** Contact ****/ %extend b2Contact { public: %pythoncode %{ def __GetWorldManifold(self): ret=b2WorldManifold() self.__GetWorldManifold_internal(ret) return ret # Read-write properties enabled = property(__IsEnabled, __SetEnabled) # Read-only next = property(__GetNext, None) fixtureB = property(__GetFixtureB, None) fixtureA = property(__GetFixtureA, None) manifold = property(__GetManifold, None) childIndexA = property(__GetChildIndexA, None) childIndexB = property(__GetChildIndexB, None) worldManifold = property(__GetWorldManifold, None) touching = property(__IsTouching, None) friction = property(__GetFriction, __SetFriction) restitution = property(__GetRestitution, __SetRestitution) tangentSpeed = property(__GetTangentSpeed, __SetTangentSpeed) %} } %rename(__GetNext) b2Contact::GetNext; %rename(__GetFixtureB) b2Contact::GetFixtureB; %rename(__GetFixtureA) b2Contact::GetFixtureA; %rename(__GetChildIndexA) b2Contact::GetChildIndexA; %rename(__GetChildIndexB) b2Contact::GetChildIndexB; %rename(__GetManifold) b2Contact::GetManifold; %rename(__GetWorldManifold_internal) b2Contact::GetWorldManifold; %rename(__IsEnabled) b2Contact::IsEnabled; %rename(__SetEnabled) b2Contact::SetEnabled; %rename(__IsTouching) b2Contact::IsTouching; %rename(__GetFriction) b2Contact::GetFriction; %rename(__SetFriction) b2Contact::SetFriction; %rename(__GetRestitution) b2Contact::GetRestitution; %rename(__SetRestitution) b2Contact::SetRestitution; %rename(__GetTangentSpeed) b2Contact::GetTangentSpeed; %rename(__SetTangentSpeed) b2Contact::SetTangentSpeed; /**** Create our own ContactPoint structure ****/ /* And allow kwargs for it */ %inline { class b2ContactPoint { public: b2ContactPoint() : fixtureA(NULL), fixtureB(NULL), state(b2_nullState) { normal.SetZero(); position.SetZero(); } ~b2ContactPoint() {} b2Fixture* fixtureA; b2Fixture* fixtureB; b2Vec2 normal; b2Vec2 position; b2PointState state; }; } /**** Replace b2TimeOfImpact ****/ %inline %{ b2TOIOutput* _b2TimeOfImpact(b2Shape* shapeA, int idxA, b2Shape* shapeB, int idxB, b2Sweep& sweepA, b2Sweep& sweepB, float32 tMax) { b2TOIInput input; b2TOIOutput* out=new b2TOIOutput; input.proxyA.Set(shapeA, idxA); input.proxyB.Set(shapeB, idxB); input.sweepA = sweepA; input.sweepB = sweepB; input.tMax = tMax; b2TimeOfImpact(out, &input); return out; } b2TOIOutput* _b2TimeOfImpact(b2TOIInput* input) { b2TOIOutput* out=new b2TOIOutput; b2TimeOfImpact(out, input); return out; } %} %pythoncode %{ def b2TimeOfImpact(shapeA=None, idxA=0, shapeB=None, idxB=0, sweepA=None, sweepB=None, tMax=0.0): """ Compute the upper bound on time before two shapes penetrate. Time is represented as a fraction between [0,tMax]. This uses a swept separating axis and may miss some intermediate, non-tunneling collision. If you change the time interval, you should call this function again. Note: use b2Distance to compute the contact point and normal at the time of impact. Can be called one of several ways: + b2TimeOfImpact(b2TOIInput) # utilizes the b2TOIInput structure, where you define your own proxies Or utilizing kwargs: + b2TimeOfImpact(shapeA=a, shapeB=b, idxA=0, idxB=0, sweepA=sa, sweepB=sb, tMax=t) Where idxA and idxB are optional and used only if the shapes are loops (they indicate which section to use.) sweep[A,B] are of type b2Sweep. Returns a tuple in the form: (output state, time of impact) Where output state is in b2TOIOutput.[ e_unknown, e_failed, e_overlapped, e_touching, e_separated ] """ if isinstance(shapeA, b2TOIInput): toi_input = shapeA out = _b2TimeOfImpact(toi_input) else: out = _b2TimeOfImpact(shapeA, idxA, shapeB, idxB, sweepA, sweepB, tMax) return (out.state, out.t) %} %newobject _b2TimeOfImpact; %ignore b2TimeOfImpact;