Browse Source

Allow for near callbacks in python

rdb 17 years ago
parent
commit
32ec0dd1c6
2 changed files with 59 additions and 9 deletions
  1. 44 6
      panda/src/ode/odeSpace.cxx
  2. 15 3
      panda/src/ode/odeSpace.h

+ 44 - 6
panda/src/ode/odeSpace.cxx

@@ -15,6 +15,13 @@
 #include "config_ode.h"
 #include "odeSpace.h"
 
+#ifdef HAVE_PYTHON
+  #include "py_panda.h"
+  #include "typedReferenceCount.h"
+  #ifndef CPPPARSER
+    extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeGeom;
+  #endif
+#endif
 
 TypeHandle OdeSpace::_type_handle;
 // this data is used in auto_collide
@@ -25,6 +32,9 @@ dJointGroupID OdeSpace::_collide_joint_group;
 int OdeSpace::contactCount = 0;
 double OdeSpace::contact_data[192];
 int OdeSpace::contact_ids[128];
+#ifdef HAVE_PYTHON
+PyObject* OdeSpace::_python_callback = NULL;
+#endif
 
 OdeSpace::
 OdeSpace(dSpaceID id) : 
@@ -103,7 +113,7 @@ set_auto_collide_joint_group(OdeJointGroup &joint_group)
 }
 
 int OdeSpace::
-autoCollide()
+auto_collide()
 {
     if (my_world == NULL) {
       odespace_cat.error() << "No collide world has been set!\n";
@@ -112,7 +122,7 @@ autoCollide()
       OdeSpace::contactCount = 0;
       _collide_space = this;
       _collide_world = my_world;
-      dSpaceCollide(_id, this, &autoCallback);
+      dSpaceCollide(_id, this, &auto_callback);
       return OdeSpace::contactCount;
     }
 }
@@ -144,11 +154,8 @@ get_contact_id(int data_index, int first)
     }
 }
 
-
-
-
 void OdeSpace::
-autoCallback(void *data, dGeomID o1, dGeomID o2)
+auto_callback(void *data, dGeomID o1, dGeomID o2)
 // uses data stored on the world to resolve collisions so you don't have to use near_callbacks in python
 {
     int i;
@@ -210,6 +217,37 @@ autoCallback(void *data, dGeomID o1, dGeomID o2)
 
 }
 
+#ifdef HAVE_PYTHON
+int OdeSpace::
+collide(PyObject* arg, PyObject* callback) {
+    nassertr(callback != NULL, -1);
+    if (!PyCallable_Check(callback)) {
+        PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callback->ob_type->tp_name);
+        return -1;
+    } else {
+        OdeSpace::_python_callback = (PyObject*) callback;
+        Py_XINCREF(OdeSpace::_python_callback);
+        dSpaceCollide(_id, (void*) arg, &near_callback);
+        Py_XDECREF(OdeSpace::_python_callback);
+        return 0;
+    }
+}
+
+void OdeSpace::
+near_callback(void *data, dGeomID o1, dGeomID o2) {
+    odespace_cat.spam() << "near_callback called, data: " << data << ", dGeomID1: " << o1 << ", dGeomID2: " << o2 << "\n";
+    OdeGeom g1 (o1);
+    OdeGeom g2 (o2);
+    PyObject* p1 = DTool_CreatePyInstanceTyped(&g1, Dtool_OdeGeom, true, false, g1.get_type_index());
+    PyObject* p2 = DTool_CreatePyInstanceTyped(&g2, Dtool_OdeGeom, true, false, g2.get_type_index());
+    PyObject* result = PyEval_CallFunction(_python_callback, "OOO", (PyObject*) data, p1, p2);
+    if (!result) {
+        odespace_cat.error() << "An error occurred while calling python function!\n";
+        PyErr_Print();
+    }
+}
+#endif
+
 OdeSimpleSpace OdeSpace::
 convert_to_simple_space() const {
   nassertr(_id != 0, OdeSimpleSpace((dSpaceID)0));

+ 15 - 3
panda/src/ode/odeSpace.h

@@ -26,6 +26,11 @@
 
 #include "ode_includes.h"
 
+#ifdef HAVE_PYTHON
+  #include "py_panda.h"
+  #include "Python.h"
+#endif
+
 class OdeGeom;
 class OdeTriMeshGeom;
 class OdeSimpleSpace;
@@ -85,11 +90,15 @@ PUBLISHED:
   OdeHashSpace convert_to_hash_space() const;
   OdeQuadTreeSpace convert_to_quad_tree_space() const;
   
-  int autoCollide();
-  static void autoCallback(void*, dGeomID, dGeomID);
+  int auto_collide();
+  static void auto_callback(void*, dGeomID, dGeomID);
+#ifdef HAVE_PYTHON
+  int collide(PyObject* arg, PyObject* near_callback);
+  static void near_callback(void*, dGeomID, dGeomID);
+#endif
   static double get_contact_data(int data_index);
   int get_contact_id(int data_index, int first = 0);
-  int set_collide_id( int collide_id, dGeomID id);
+  int set_collide_id(int collide_id, dGeomID id);
   int set_collide_id(OdeGeom& geom, int collide_id);
   void set_surface_type( int surface_type, dGeomID id);
   void set_surface_type(OdeGeom& geom, int surface_type);
@@ -104,6 +113,9 @@ public:
   static OdeWorld* _collide_world;
   static OdeSpace* _collide_space;
   static dJointGroupID _collide_joint_group;
+#ifdef HAVE_PYTHON
+  static PyObject* _python_callback;
+#endif
   static int contactCount;
 
   static double contact_data[192]; // 64 times three