From 35062a76c7d1302cd92cb55ef74fc1392241640b Mon Sep 17 00:00:00 2001 From: Stephane Delcroix Date: Fri, 1 Mar 2013 12:30:34 +0100 Subject: [PATCH 1/3] [chipmunk] Space.AddPostStepCallback --- chipmunk/binding/src/Space.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/chipmunk/binding/src/Space.cs b/chipmunk/binding/src/Space.cs index bbde346e..1a27151d 100644 --- a/chipmunk/binding/src/Space.cs +++ b/chipmunk/binding/src/Space.cs @@ -243,6 +243,20 @@ public bool Contains (Constraint constraint) return cpSpaceContainsConstraint (Handle.Handle, constraint.Handle.Handle); } + delegate void PostStepFunc (IntPtr space, IntPtr obj, IntPtr data); + + [DllImport ("__Internal")] + extern static void cpSpaceAddPostStepCallback (IntPtr space, PostStepFunc func, IntPtr key, IntPtr data); + + public void AddPostStepCallback (Action action, T obj) where T : ChipmunkObject + { + PostStepFunc func = (space, o, data) => { + action (this, o == IntPtr.Zero ? null : (T)(object)new Body (o)); + }; + + cpSpaceAddPostStepCallback (Handle.Handle, func, obj.Handle.Handle, IntPtr.Zero); + } + [DllImport("__Internal")] extern static IntPtr cpSpaceAddStaticShape (IntPtr space, IntPtr shape); From 52a8e6eb77fe97fd679b9e47c4dddabf72526b0a Mon Sep 17 00:00:00 2001 From: Stephane Delcroix Date: Fri, 1 Mar 2013 12:48:15 +0100 Subject: [PATCH 2/3] [chipmunk] equality comparers implement ==, !=, Equals and GetHashCode on ChipmunkObject. Seal Arbiter, Body, Constraints, Shapes and Space to avoid issues in user code. Really need inheritance ? Think twice, and compose. --- chipmunk/binding/src/Arbiter.cs | 2 +- chipmunk/binding/src/Body.cs | 2 +- chipmunk/binding/src/ChipmunkObject.cs | 30 ++++++++++++++++++++++++++ chipmunk/binding/src/Constraint.cs | 21 +++++++++--------- chipmunk/binding/src/Shape.cs | 6 +++--- chipmunk/binding/src/Space.cs | 2 +- 6 files changed, 46 insertions(+), 17 deletions(-) diff --git a/chipmunk/binding/src/Arbiter.cs b/chipmunk/binding/src/Arbiter.cs index c5120830..c8e7dbb9 100644 --- a/chipmunk/binding/src/Arbiter.cs +++ b/chipmunk/binding/src/Arbiter.cs @@ -15,7 +15,7 @@ namespace Chipmunk { - public partial class Arbiter : ChipmunkObject + public sealed partial class Arbiter : ChipmunkObject { public Arbiter (IntPtr ptr) : base (ptr, false) { diff --git a/chipmunk/binding/src/Body.cs b/chipmunk/binding/src/Body.cs index 71cbc31c..14b1d427 100644 --- a/chipmunk/binding/src/Body.cs +++ b/chipmunk/binding/src/Body.cs @@ -20,7 +20,7 @@ namespace Chipmunk { - public partial class Body : ChipmunkObject + public sealed partial class Body : ChipmunkObject { public Body (IntPtr ptr) : base (ptr) { diff --git a/chipmunk/binding/src/ChipmunkObject.cs b/chipmunk/binding/src/ChipmunkObject.cs index 1cbed351..ed1a9ad8 100644 --- a/chipmunk/binding/src/ChipmunkObject.cs +++ b/chipmunk/binding/src/ChipmunkObject.cs @@ -39,6 +39,36 @@ protected ChipmunkObject (IntPtr ptr, bool refcount = true) AddRef (this, ptr); } + public static bool operator ==(ChipmunkObject a, ChipmunkObject b) + { + if (System.Object.ReferenceEquals (a, b)) + return true; + + if (((object)a == null) || ((object)b == null)) + return false; + + return a.Handle.Handle == b.Handle.Handle; + } + + public static bool operator != (ChipmunkObject a, ChipmunkObject b) + { + return !(a == b); + } + + public override bool Equals (System.Object obj) + { + var other = obj as ChipmunkObject; + if ((object)other == null) + return false; + + return this == other; + } + + public override int GetHashCode () + { + return Handle.Handle.GetHashCode (); + } + ~ChipmunkObject () { Cleanup (); diff --git a/chipmunk/binding/src/Constraint.cs b/chipmunk/binding/src/Constraint.cs index 7cdd6e32..32f78d9a 100644 --- a/chipmunk/binding/src/Constraint.cs +++ b/chipmunk/binding/src/Constraint.cs @@ -89,7 +89,7 @@ protected override void Free () } - public partial class PinJoint : Constraint + public sealed partial class PinJoint : Constraint { [DllImport ("__Internal")] extern static IntPtr cpPinJointNew (IntPtr bodyA, IntPtr bodyB, PointF anchr1, PointF anchr2); @@ -132,7 +132,7 @@ public PinJoint (Body bodyA, Body bodyB, PointF anchr1, PointF anchr2) : base (c } } - public partial class SlideJoint : Constraint + public sealed partial class SlideJoint : Constraint { [DllImport ("__Internal")] extern static IntPtr cpSlideJointNew (IntPtr bodyA, IntPtr bodyB, PointF anchr1, PointF anchr2, float min, float max); @@ -186,7 +186,7 @@ public SlideJoint (Body bodyA, Body bodyB, PointF anchr1, PointF anchr2, float m } } - public partial class PivotJoint : Constraint + public sealed partial class PivotJoint : Constraint { [DllImport ("__Internal")] extern static IntPtr cpPivotJointNew (IntPtr bodyA, IntPtr bodyB, PointF pivot); @@ -225,7 +225,7 @@ public PivotJoint (Body bodyA, Body bodyB, PointF anchr1, PointF anchr2) : base } } - public partial class GrooveJoint : Constraint + public sealed partial class GrooveJoint : Constraint { [DllImport ("__Internal")] extern static IntPtr cpGrooveJointNew (IntPtr bodyA, IntPtr bodyB, PointF grooveA, PointF grooveB, PointF anchr2); @@ -268,7 +268,7 @@ public GrooveJoint (Body bodyA, Body bodyB, PointF grooveA, PointF grooveB, Poin } } - public partial class DampedSpring : Constraint + public sealed partial class DampedSpring : Constraint { [DllImport("__Internal")] extern static IntPtr cpDampedSpringNew (IntPtr bodyA, IntPtr bodyB, PointF anchr1, PointF anchr2, float restLength, float stiffness, float damping); @@ -333,7 +333,7 @@ public DampedSpring (Body bodyA, Body bodyB, PointF anchr1, PointF anchr2, float } } - public partial class DampedRotarySpring : Constraint + public sealed partial class DampedRotarySpring : Constraint { [DllImport ("__Internal")] extern static IntPtr cpDampedRotarySpringNew (IntPtr bodyA, IntPtr bodyB, float restAngle, float stiffness, float damping); @@ -376,7 +376,7 @@ public DampedRotarySpring (Body bodyA, Body bodyB, float restAngle, float stiffn } } - public partial class RotaryLimitJoint : Constraint + public sealed partial class RotaryLimitJoint : Constraint { [DllImport ("__Internal")] extern static IntPtr cpRotaryLimitJointNew (IntPtr bodyA, IntPtr bodyB, float min, float max); @@ -408,7 +408,7 @@ public RotaryLimitJoint (Body bodyA, Body bodyB, float min, float max) : base (c } } - public partial class RatchetJoint : Constraint + public sealed partial class RatchetJoint : Constraint { [DllImport ("__Internal")] extern static IntPtr cpRatchetJointNew (IntPtr bodyA, IntPtr bodyB, float phase, float ratchet); @@ -451,7 +451,7 @@ public RatchetJoint (Body bodyA, Body bodyB, float phase, float ratchet) : base } } - public partial class GearJoint : Constraint + public sealed partial class GearJoint : Constraint { [DllImport ("__Internal")] extern static IntPtr cpGearJointNew (IntPtr bodyA, IntPtr bodyB, float pahse, float ratio); @@ -483,7 +483,7 @@ public GearJoint (Body bodyA, Body bodyB, float phase, float ratio) : base (cpGe } } - public partial class SimpleMotor : Constraint + public sealed partial class SimpleMotor : Constraint { [DllImport ("__Internal")] extern static IntPtr cpSimpleMotorNew (IntPtr bodyA, IntPtr bodyB, float rate); @@ -504,4 +504,3 @@ public SimpleMotor (Body bodyA, Body bodyB, float rate) : base (cpSimpleMotorNew } } } - diff --git a/chipmunk/binding/src/Shape.cs b/chipmunk/binding/src/Shape.cs index 0a76ed30..e495d16c 100644 --- a/chipmunk/binding/src/Shape.cs +++ b/chipmunk/binding/src/Shape.cs @@ -156,7 +156,7 @@ public RectangleF Update (PointF position, PointF rotation) public extern static void ResetShapeIdCounter (); } - public partial class CircleShape : Shape + public sealed partial class CircleShape : Shape { [DllImport ("__Internal")] extern static IntPtr cpCircleShapeNew (IntPtr body, float radius, PointF offset); @@ -180,7 +180,7 @@ public CircleShape (Body body, float radius, PointF offset) : base (cpCircleShap } } - public partial class SegmentShape:Shape + public sealed partial class SegmentShape:Shape { [DllImport("__Internal")] extern static IntPtr cpSegmentShapeNew (IntPtr body, PointF a, PointF b, float radius); @@ -218,7 +218,7 @@ public SegmentShape (Body body, PointF a, PointF b, float radius) : base (cpSegm } } - public partial class PolygonShape : Shape + public sealed partial class PolygonShape : Shape { [DllImport("__Internal")] extern static IntPtr cpPolyShapeNew (IntPtr body, int numVerts, PointF[] verts, PointF offset); diff --git a/chipmunk/binding/src/Space.cs b/chipmunk/binding/src/Space.cs index 1a27151d..e2bd0f23 100644 --- a/chipmunk/binding/src/Space.cs +++ b/chipmunk/binding/src/Space.cs @@ -17,7 +17,7 @@ namespace Chipmunk { - public partial class Space : ChipmunkObject + public sealed partial class Space : ChipmunkObject { [DllImport ("__Internal")] extern static IntPtr cpSpaceNew (); From db193d26b63d52b7b4299737e13b886a99312f6d Mon Sep 17 00:00:00 2001 From: Stephane Delcroix Date: Fri, 1 Mar 2013 14:43:38 +0100 Subject: [PATCH 3/3] [chipmunk] Fix the callback passed to native The callback used to work... on the simulator, but failed when I tried them on a device. This adds a nice layer of abstraction to hide the fact that you have to flag the callbacks with [MonoPInvokeCallback] and that you can't have instance methods. --- chipmunk/binding/src/Space.cs | 129 +++++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 34 deletions(-) diff --git a/chipmunk/binding/src/Space.cs b/chipmunk/binding/src/Space.cs index e2bd0f23..a3c5e1a7 100644 --- a/chipmunk/binding/src/Space.cs +++ b/chipmunk/binding/src/Space.cs @@ -242,21 +242,7 @@ public bool Contains (Constraint constraint) { return cpSpaceContainsConstraint (Handle.Handle, constraint.Handle.Handle); } - - delegate void PostStepFunc (IntPtr space, IntPtr obj, IntPtr data); - - [DllImport ("__Internal")] - extern static void cpSpaceAddPostStepCallback (IntPtr space, PostStepFunc func, IntPtr key, IntPtr data); - - public void AddPostStepCallback (Action action, T obj) where T : ChipmunkObject - { - PostStepFunc func = (space, o, data) => { - action (this, o == IntPtr.Zero ? null : (T)(object)new Body (o)); - }; - - cpSpaceAddPostStepCallback (Handle.Handle, func, obj.Handle.Handle, IntPtr.Zero); - } - + [DllImport("__Internal")] extern static IntPtr cpSpaceAddStaticShape (IntPtr space, IntPtr shape); @@ -293,43 +279,67 @@ public void ReindexStaticShapes () } //iterators - delegate void BodyIterator (IntPtr body, IntPtr data); + delegate void BodyIteratorFunc (IntPtr body, IntPtr data); + [MonoTouch.MonoPInvokeCallback (typeof (BodyIteratorFunc))] + static void BodyIterator (IntPtr body, IntPtr data) + { + var handle = GCHandle.FromIntPtr (data); + var action = (Action)handle.Target; + action (new Body(body)); + } + [DllImport ("__Internal")] - extern static void cpSpaceEachBody (IntPtr space, BodyIterator iterator, IntPtr data); + extern static void cpSpaceEachBody (IntPtr space, BodyIteratorFunc iterator, IntPtr data); public void EachBody (Action action) { - BodyIterator iterator = (body, data) => { - action (new Body (body)); - }; - cpSpaceEachBody (Handle.Handle, iterator, IntPtr.Zero); + var handle = GCHandle.Alloc (action); + var data = GCHandle.ToIntPtr(handle); + cpSpaceEachBody (Handle.Handle, BodyIterator, data); + handle.Free (); } - delegate void ShapeIterator (IntPtr shape, IntPtr data); + delegate void ShapeIteratorFunc (IntPtr shape, IntPtr data); + [MonoTouch.MonoPInvokeCallback (typeof (ShapeIteratorFunc))] + static void ShapeIterator (IntPtr shape, IntPtr data) + { + var handle = GCHandle.FromIntPtr (data); + var action = (Action)handle.Target; + action (new Shape(shape)); + } + [DllImport ("__Internal")] - extern static void cpSpaceEachShape (IntPtr space, ShapeIterator iterator, IntPtr data); + extern static void cpSpaceEachShape (IntPtr space, ShapeIteratorFunc iterator, IntPtr data); public void EachShape (Action action) { - ShapeIterator iterator = (shape, data) => { - action (new Shape(shape)); - }; - cpSpaceEachShape (Handle.Handle, iterator, IntPtr.Zero); + var handle = GCHandle.Alloc (action); + var data = GCHandle.ToIntPtr(handle); + cpSpaceEachShape (Handle.Handle, ShapeIterator, data); + handle.Free (); } - delegate void ConstraintIterator (IntPtr constraint, IntPtr data); + delegate void ConstraintIteratorFunc (IntPtr constraint, IntPtr data); + [MonoTouch.MonoPInvokeCallback (typeof (ConstraintIteratorFunc))] + static void ConstraintIterator (IntPtr constraint, IntPtr data) + { + var handle = GCHandle.FromIntPtr (data); + var action = (Action)handle.Target; + action (new Constraint (constraint)); + } + [DllImport ("__Internal")] - extern static void cpSpaceEachConstraint(IntPtr body, ConstraintIterator iterator, IntPtr data); + extern static void cpSpaceEachConstraint(IntPtr body, ConstraintIteratorFunc iterator, IntPtr data); public void EachConstraint (Action action) { - ConstraintIterator iterator = (constraint, data) => { - action (new Constraint(constraint)); - }; - cpSpaceEachConstraint (Handle.Handle, iterator, IntPtr.Zero); + var handle = GCHandle.Alloc (action); + var data = GCHandle.ToIntPtr(handle); + cpSpaceEachConstraint (Handle.Handle, ConstraintIterator, data); + handle.Free (); } //simulating the space @@ -338,9 +348,60 @@ public void EachConstraint (Action action) public void Step (float dt) { - cpSpaceStep(Handle.Handle, dt); + cpSpaceStep(Handle.Handle, dt); } + //Post step + delegate void PostStepFunc (IntPtr space, IntPtr obj, IntPtr data); + + [MonoTouch.MonoPInvokeCallback (typeof (PostStepFunc))] + static void PostStepForBody (IntPtr space, IntPtr obj, IntPtr data) + { + var handle = GCHandle.FromIntPtr (data); + var action = (Action)handle.Target; + handle.Free (); + action (obj == IntPtr.Zero ? null : new Body (obj)); + } + + [MonoTouch.MonoPInvokeCallback (typeof (PostStepFunc))] + static void PostStepForShape (IntPtr space, IntPtr obj, IntPtr data) + { + var handle = GCHandle.FromIntPtr (data); + var action = (Action)handle.Target; + handle.Free (); + action (obj == IntPtr.Zero ? null : new Shape (obj)); + } + + [MonoTouch.MonoPInvokeCallback (typeof (PostStepFunc))] + static void PostStepForConstraint (IntPtr space, IntPtr obj, IntPtr data) + { + var handle = GCHandle.FromIntPtr (data); + var action = (Action)handle.Target; + handle.Free (); + action (obj == IntPtr.Zero ? null : new Constraint (obj)); + } + + [DllImport ("__Internal")] + extern static void cpSpaceAddPostStepCallback (IntPtr space, PostStepFunc func, IntPtr key, IntPtr data); + + public void AddPostStepCallback (Action action, Body obj) + { + var data = GCHandle.ToIntPtr(GCHandle.Alloc (action)); + cpSpaceAddPostStepCallback (Handle.Handle, PostStepForBody, obj.Handle.Handle, data); + } + + public void AddPostStepCallback (Action action, Shape obj) + { + var data = GCHandle.ToIntPtr(GCHandle.Alloc (action)); + cpSpaceAddPostStepCallback (Handle.Handle, PostStepForShape, obj.Handle.Handle, data); + } + + public void AddPostStepCallback (Action action, Constraint obj) + { + var data = GCHandle.ToIntPtr(GCHandle.Alloc (action)); + cpSpaceAddPostStepCallback (Handle.Handle, PostStepForConstraint, obj.Handle.Handle, data); + } + //spatial hash [DllImport ("__Internal")] extern static void cpSpaceUseSpatialHash(IntPtr space, float dim, int count);