OSDN Git Service

Add contact callback filter
authorXoppa <contact@xoppa.nl>
Wed, 20 Mar 2013 17:31:32 +0000 (18:31 +0100)
committerXoppa <contact@xoppa.nl>
Wed, 20 Mar 2013 17:31:32 +0000 (18:31 +0100)
extensions/gdx-bullet/jni/src/GdxCustom/ContactAddedListener.h
extensions/gdx-bullet/jni/src/GdxCustom/ContactDestroyedListener.h
extensions/gdx-bullet/jni/src/GdxCustom/ContactProcessedListener.h
extensions/gdx-bullet/jni/src/GdxCustom/GdxCollisionObjectBridge.h
extensions/gdx-bullet/jni/swig/custom/ContactListener.i
extensions/gdx-bullet/jni/swig/custom/btCollisionObject.i

index c9d7a84..19d941d 100644 (file)
@@ -22,6 +22,7 @@ static bool ContactAddedListener_CB(btManifoldPoint& cp,const btCollisionObjectW
 BaseContactAddedListener *currentContactAddedListener = 0;
 
 /** @author Xoppa */
+#ifndef SWIG
 class BaseContactAddedListener {
 public:
        BaseContactAddedListener() {
@@ -32,9 +33,8 @@ public:
                disable();
        }
 
-       virtual bool internalCallback(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) {
-               return false;
-       }
+       virtual bool internalCallback(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,
+                       const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0;
 
        void enable() {
                currentContactAddedListener = this;
@@ -52,41 +52,53 @@ public:
                return currentContactAddedListener == this;
        }
 };
+#endif // SWIG
 
 class ContactAddedListenerByWrapper : public BaseContactAddedListener {
 public:
-       bool internalCallback(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) {
-               return onContactAdded(cp, colObj0Wrap, partId0, index0, colObj1Wrap, partId1, index1);
-       }
+       virtual bool onContactAdded(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,bool match0,
+                       const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1,bool match1) = 0;
 
-       virtual bool onContactAdded(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) {
-               return false;
+#ifndef SWIG
+       bool internalCallback(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) {
+               bool match0 = gdxCheckFilter(colObj0Wrap->m_collisionObject, colObj1Wrap->m_collisionObject);
+               bool match1 = gdxCheckFilter(colObj1Wrap->m_collisionObject, colObj0Wrap->m_collisionObject);
+               return (match0 || match1) ? onContactAdded(cp, colObj0Wrap, partId0, index0, match0, colObj1Wrap, partId1, index1, match1) : false;
        }
+#endif // SWIG
 };
 
 class ContactAddedListenerByObject : public BaseContactAddedListener {
 public:
-       bool internalCallback(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) {
-               return onContactAdded(cp, colObj0Wrap->m_collisionObject, partId0, index0, colObj1Wrap->m_collisionObject, partId1, index1);
-       }
+       virtual bool onContactAdded(btManifoldPoint& cp,const btCollisionObject* colObj0,int partId0,int index0,bool match0,
+                       const btCollisionObject* colObj1,int partId1,int index1,bool match1) = 0;
 
-       virtual bool onContactAdded(btManifoldPoint& cp,const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) {
-               return false;
+#ifndef SWIG
+       bool internalCallback(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) {
+               bool match0 = gdxCheckFilter(colObj0Wrap->m_collisionObject, colObj1Wrap->m_collisionObject);
+               bool match1 = gdxCheckFilter(colObj1Wrap->m_collisionObject, colObj0Wrap->m_collisionObject);
+               return (match0 || match1) ? onContactAdded(cp, colObj0Wrap->m_collisionObject, partId0, index0, match0, colObj1Wrap->m_collisionObject, partId1, index1, match1) : false;
        }
+#endif // SWIG
 };
 
 class ContactAddedListenerByValue : public BaseContactAddedListener {
 public:
+       virtual bool onContactAdded(btManifoldPoint& cp,int userValue0,int partId0,int index0,bool match0,
+                       int userValue1,int partId1,int index1,bool match1) = 0;
+
+#ifndef SWIG
        bool internalCallback(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) {
+               bool match0 = gdxCheckFilter(colObj0Wrap->m_collisionObject, colObj1Wrap->m_collisionObject);
+               bool match1 = gdxCheckFilter(colObj1Wrap->m_collisionObject, colObj0Wrap->m_collisionObject);
+               if (!match0 && !match1)
+                       return false;
                int val0, val1;
                val0 = ((GdxCollisionObjectBridge*)(colObj0Wrap->m_collisionObject->getUserPointer()))->userValue;
                val1 = ((GdxCollisionObjectBridge*)(colObj1Wrap->m_collisionObject->getUserPointer()))->userValue;
-               return onContactAdded(cp, val0, partId0, index0, val1, partId1, index1);
-       }
-
-       virtual bool onContactAdded(btManifoldPoint& cp,int userValue0,int partId0,int index0,int userValue1,int partId1,int index1) {
-               return false;
+               return onContactAdded(cp, val0, partId0, index0, match0, val1, partId1, index1, match1);
        }
+#endif // SWIG
 };
 
 bool ContactAddedListener_CB(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) {
index 8564f0b..a0cacc9 100644 (file)
@@ -32,15 +32,16 @@ public:
                disable();
        }
 
+       virtual void onContactDestroyed(int manifoldPointUserValue) = 0;
+
+#ifndef SWIG
        bool internalCallback(void *userPersistentData) {
                int val;
                *(const void **)&val = userPersistentData;
-               return onContactDestroyed(val);
-       }
-
-       virtual bool onContactDestroyed(int manifoldPointUserValue) {
+               onContactDestroyed(val);
                return false;
        }
+#endif // SWIG
 
        void enable() {
                currentContactDestroyedListener = this;
index d5f8fdb..4b467c2 100644 (file)
@@ -22,6 +22,7 @@ static bool ContactProcessedListener_CB(btManifoldPoint& cp,void *body0, void *b
 BaseContactProcessedListener *currentContactProcessedListener = 0;
 
 /** @author Xoppa */
+#ifndef SWIG
 class BaseContactProcessedListener {
 public:
        BaseContactProcessedListener() {
@@ -32,9 +33,7 @@ public:
                disable();
        }
 
-       virtual bool internalCallback(btManifoldPoint& cp,void *body0, void *body1) {
-               return false;
-       }
+       virtual bool internalCallback(btManifoldPoint& cp,void *body0, void *body1) = 0;
 
        void enable() {
                currentContactProcessedListener = this;
@@ -52,30 +51,41 @@ public:
                return currentContactProcessedListener == this;
        }
 };
+#endif //SWIG
 
 class ContactProcessedListenerByObject : public BaseContactProcessedListener {
 public:
-       bool internalCallback(btManifoldPoint& cp,void *body0, void *body1) {
-               return onContactProcessed(cp, (btCollisionObject*)body0, (btCollisionObject*)body1);
-       }
+       virtual void onContactProcessed(btManifoldPoint& cp, const btCollisionObject* colObj0, bool match0,
+                       const btCollisionObject* colObj1, bool match1) = 0;
 
-       virtual bool onContactProcessed(btManifoldPoint& cp, const btCollisionObject* colObj0, const btCollisionObject* colObj1) {
+#ifndef SWIG
+       bool internalCallback(btManifoldPoint& cp,void *body0, void *body1) {
+               bool match0 = gdxCheckFilter((btCollisionObject*)body0, (btCollisionObject*)body1);
+               bool match1 = gdxCheckFilter((btCollisionObject*)body1, (btCollisionObject*)body0);
+               if (match0 || match1)
+                       onContactProcessed(cp, (btCollisionObject*)body0, match0, (btCollisionObject*)body1, match1);
                return false;
        }
+#endif // SWIG
 };
 
 class ContactProcessedListenerByValue : public BaseContactProcessedListener {
 public:
-       bool internalCallback(btManifoldPoint& cp,void *body0, void *body1) {
-               int val0, val1;
-               val0 = ((GdxCollisionObjectBridge*)(((btCollisionObject*)body0)->getUserPointer()))->userValue;
-               val1 = ((GdxCollisionObjectBridge*)(((btCollisionObject*)body1)->getUserPointer()))->userValue;
-               return onContactProcessed(cp, val0, val1);
-       }
+       virtual bool onContactProcessed(btManifoldPoint& cp,int userValue0,bool match0,int userValue1,bool match1) = 0;
 
-       virtual bool onContactProcessed(btManifoldPoint& cp,int userValue0,int userValue1) {
+#ifndef SWIG
+       bool internalCallback(btManifoldPoint& cp,void *body0, void *body1) {
+               bool match0 = gdxCheckFilter((btCollisionObject*)body0, (btCollisionObject*)body1);
+               bool match1 = gdxCheckFilter((btCollisionObject*)body1, (btCollisionObject*)body0);
+               if (match0 || match1) {
+                       int val0, val1;
+                       val0 = ((GdxCollisionObjectBridge*)(((btCollisionObject*)body0)->getUserPointer()))->userValue;
+                       val1 = ((GdxCollisionObjectBridge*)(((btCollisionObject*)body1)->getUserPointer()))->userValue;
+                       onContactProcessed(cp, val0, match0, val1, match1);
+               }
                return false;
        }
+#endif // SWIG
 };
 
 bool ContactProcessedListener_CB(btManifoldPoint& cp,void *body0, void *body1) {
index 897b815..36b9629 100644 (file)
 class GdxCollisionObjectBridge {
 public:
        int userValue;
+       int contactCallbackFlag;
+       int contactCallbackFilter;
+
+       GdxCollisionObjectBridge() : userValue(0), contactCallbackFlag(1), contactCallbackFilter(0)
+       {}
 };
 
+inline bool gdxCheckFilter(const int filter, const int flag) {
+       return (filter & flag) == flag;
+}
+
+inline bool gdxCheckFilter(const btCollisionObject* colObj0, const btCollisionObject* colObj1) {
+       return gdxCheckFilter(((GdxCollisionObjectBridge*)(colObj0->getUserPointer()))->contactCallbackFilter,
+                       ((GdxCollisionObjectBridge*)(colObj1->getUserPointer()))->contactCallbackFlag);
+}
+
 #endif // GdxCollsionObjectBridge_H
index c39121b..037d7be 100644 (file)
 #include <GdxCustom/ContactProcessedListener.h>
 #include <GdxCustom/ContactDestroyedListener.h>
 %}
-
-class BaseContactAddedListener {
-public:
-       void enable();
-       void disable();
-       bool isEnabled();
-};
-
-class ContactAddedListenerByWrapper : public BaseContactAddedListener {
-public:
-       virtual bool onContactAdded(btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0;
-};
-
-class ContactAddedListenerByObject : public BaseContactAddedListener {
-public:
-       virtual bool onContactAdded(btManifoldPoint& cp,const btCollisionObject* colObj0Wrap,int partId0,int index0,const btCollisionObject* colObj1Wrap,int partId1,int index1) = 0;
-};
-
-class ContactAddedListenerByValue : public BaseContactAddedListener {
-public:
-       virtual bool onContactAdded(btManifoldPoint& cp,int userValue0,int partId0,int index0,int userValue1,int partId1,int index1) = 0;
-};
-
-class BaseContactProcessedListener {
-public:
-       void enable();
-       void disable();
-       bool isEnabled();
-};
-
-class ContactProcessedListenerByObject : public BaseContactProcessedListener {
-public:
-       virtual bool onContactProcessed(btManifoldPoint& cp, const btCollisionObject* colObj0, const btCollisionObject* colObj1) = 0;
-};
-
-class ContactProcessedListenerByValue : public BaseContactProcessedListener {
-public:
-       virtual bool onContactProcessed(btManifoldPoint& cp,int userValue0,int userValue1) = 0;
-};
-
-class ContactDestroyedListener {
-public:
-       virtual bool onContactDestroyed(int manifoldPointUserValue) = 0;
-       void enable();
-       void disable();
-       bool isEnabled();
-};
\ No newline at end of file
+%include "GdxCustom/ContactAddedListener.h"
+%include "GdxCustom/ContactProcessedListener.h"
+%include "GdxCustom/ContactDestroyedListener.h"
index 40d6c9b..16ffb2f 100644 (file)
 %}\r
 \r
 %typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") btCollisionObject %{ {\r
-    if (gdxBridge != null) {\r
+    if (swigCPtr != 0)\r
+      removeInstance(this);\r
+       if (gdxBridge != null) {\r
        gdxBridge.delete();\r
        gdxBridge = null;\r
     }\r
     if (swigCPtr != 0) {\r
-      instances.remove(swigCPtr);\r
       if (swigCMemOwn) {\r
         swigCMemOwn = false;\r
         gdxBulletJNI.delete_btCollisionObject(swigCPtr);\r
 %typemap(javabody) btCollisionObject %{\r
        public final static com.badlogic.gdx.utils.LongMap<btCollisionObject> instances = new com.badlogic.gdx.utils.LongMap<btCollisionObject>();\r
        \r
+       public static btCollisionObject getInstance(final long swigCPtr) {\r
+               return instances.get(swigCPtr);\r
+       }\r
+       \r
        public static btCollisionObject getInstance(final long swigCPtr, boolean owner) {\r
-               btCollisionObject result = instances.get(swigCPtr);\r
+               btCollisionObject result = getInstance(swigCPtr);\r
                if (result == null)\r
                        result = new btCollisionObject(swigCPtr, owner);\r
                return result;\r
        }\r
        \r
+       public static void addInstance(final btCollisionObject obj) {\r
+               instances.put(getCPtr(obj), obj);\r
+       }\r
+       \r
+       public static void removeInstance(final btCollisionObject obj) {\r
+               instances.remove(getCPtr(obj));\r
+       }\r
+       \r
        private long swigCPtr;\r
        protected boolean swigCMemOwn;\r
-       public GdxCollisionObjectBridge gdxBridge;\r
+       protected GdxCollisionObjectBridge gdxBridge;\r
+       protected int userValue;\r
+       protected int contactCallbackFlag = 1;\r
+       protected int contactCallbackFilter;\r
        \r
        public Object userData;\r
        \r
        protected btCollisionObject(long cPtr, boolean cMemoryOwn) {\r
                swigCMemOwn = cMemoryOwn;\r
                swigCPtr = cPtr;\r
-               instances.put(cPtr, this);\r
                gdxBridge = new GdxCollisionObjectBridge();\r
                internalSetGdxBridge(gdxBridge);\r
+               addInstance(this);\r
        }\r
        \r
        @Override\r
        public static long getCPtr($javaclassname obj) {\r
                return (obj == null) ? 0 : obj.swigCPtr;\r
        }\r
+       \r
+       /** @return A user definable value set using {@link #setUserValue(int)}, intended to quickly identify the collision object */ \r
+       public int getUserValue() {\r
+               return userValue;\r
+       }\r
+       \r
+       /** @param value A user definable value which allows you to quickly identify this collision object. Some frequently called\r
+        * methods rather return this value than the collision object itself to minimize JNI overhead. */\r
+       public void setUserValue(int value) {\r
+               gdxBridge.setUserValue(userValue = value);\r
+       }\r
+       \r
+       /** @return The flag (defaults to 1) used to filter contact callbacks with this object */\r
+       public int getContactCallbackFlag() {\r
+               return contactCallbackFlag;\r
+       }\r
+       \r
+       /** @param flag The new flag used to filter contact callbacks with this object */\r
+       public void setContactCallbackFlag(int flag) {\r
+               gdxBridge.setContactCallbackFlag(contactCallbackFlag = flag);\r
+       }\r
+       \r
+       /** @return The filter (default to 0) that is used to match the flag of the other object for a contact callback to be triggered */\r
+       public int getContactCallbackFilter() {\r
+               return contactCallbackFilter;\r
+       }\r
+       \r
+       /** @param filter The new filter that is used to match the flag of the other object for a contact callback to be triggered */\r
+       public void setContactCallbackFilter(int filter) {\r
+               gdxBridge.setContactCallbackFilter(contactCallbackFilter = filter);\r
+       }\r
 %}\r
 \r
 %{\r
        void getInterpolationAngularVelocity(btVector3 & out) {\r
                out = $self->getInterpolationAngularVelocity();\r
        }\r
-       \r
-       int getUserValue() {\r
-               return ((GdxCollisionObjectBridge*)($self->getUserPointer()))->userValue;;\r
-       }\r
-       \r
-       void setUserValue(int value) {\r
-               ((GdxCollisionObjectBridge*)($self->getUserPointer()))->userValue = value;\r
-       }\r
 };
\ No newline at end of file