<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -5,6 +5,7 @@ import vecmath._
 import vecmath.Preamble._
 import contacts._
 import joints._
+import controllers._
 
 object BodyFlags {
   val frozen = 0x0002
@@ -39,7 +40,13 @@ final class Body(bd: BodyDef, val world: World) {
 
   var contactList: List[ContactEdge] = Nil
   var jointList: List[JointEdge] = Nil
-  
+
+  // The body will be removed from these controllers when it is destroyed
+  private[dynamics] val managingControllers =
+    collection.mutable.Set[Controller with SelfManagedBodies]()
+  // These controllers will be removed from the world with the body
+  private[dynamics] val dependentControllers = collection.mutable.Set[Controller]()
+
   private[this] var _transform = Transform2(bd.pos, Matrix22.rotation(bd.angle))
   def pos = _transform.pos
   /** The swept motion for CCD */</diff>
      <filename>scalabox2d/src/main/scala/org/villane/box2d/dynamics/Body.scala</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,7 @@ package org.villane.box2d.dynamics
 
 import shapes.Shape
 import joints.Joint
+import controllers.Controller
 
 /**
  * Joints and shapes are destroyed when their associated
@@ -20,4 +21,10 @@ trait DestructionListener {
    * to the destruction of its parent body.
    */
   def sayGoodbye(fixture: Fixture)
+
+  /**
+   * Called when any controller is about to be destroyed due
+   * to the destruction of its parent body.
+   */
+  def sayGoodbye(controller: Controller)
 }</diff>
      <filename>scalabox2d/src/main/scala/org/villane/box2d/dynamics/DestructionListener.scala</filename>
    </modified>
    <modified>
      <diff>@@ -80,21 +80,26 @@ class World(val aabb: AABB, var gravity: Vector2, doSleep: Boolean) {
 
     // Delete the attached joints.
     for (jn &lt;- b.jointList) {
-      if (destructionListener != null) {
-        destructionListener.sayGoodbye(jn.joint)
-      }
+      if (destructionListener != null) destructionListener.sayGoodbye(jn.joint)
       destroyJoint(jn.joint)
     }
 
     // Delete the attached shapes. This destroys broad-phase
     // proxies and pairs, leading to the destruction of contacts.
     for (f &lt;- b.fixtures) {
-      if (destructionListener != null) {
-        destructionListener.sayGoodbye(f)
-      }
+      if (destructionListener != null) destructionListener.sayGoodbye(f)
       f.destroyProxy(broadPhase)
     }
 
+    // Remove the body from controllers
+    for (c &lt;- b.managingControllers) c.removeBody(b)
+
+    // Remove dependent controllers from the world
+    for (c &lt;- b.dependentControllers) {
+      if (destructionListener != null) destructionListener.sayGoodbye(c)
+      removeController(c)
+    }
+
     bodyList -= b
   }
 	
@@ -167,7 +172,15 @@ class World(val aabb: AABB, var gravity: Vector2, doSleep: Boolean) {
   }
 
   def addController(c: Controller) = controllers += c
-  def removeController(c: Controller) = controllers -= c
+
+  def removeController(c: Controller) = {
+    c match {
+      case ctrl: SelfManagedBodies =&gt;
+        for (b &lt;- ctrl.bodies) b.managingControllers -= ctrl
+      case _ =&gt;
+    }
+    controllers -= c
+  }
 
   /**
    * Take a time step. This performs collision detection, integration,
@@ -186,15 +199,11 @@ class World(val aabb: AABB, var gravity: Vector2, doSleep: Boolean) {
     // Update contacts.
     contactManager.collide()
 
-    // Integrate velocities, solve velocity constraints, and integrate positions.}
-    if (step.dt &gt; 0f) {
-      solve(step)
-    }
+    // Integrate velocities, solve velocity constraints, and integrate positions.
+    if (step.dt &gt; 0f) solve(step)
 
     // Handle TOI events.
-    if (continuousPhysics &amp;&amp; step.dt &gt; 0f) {
-      solveTOI(step)
-    }
+    if (continuousPhysics &amp;&amp; step.dt &gt; 0f) solveTOI(step)
 
     if (step.dt &gt; 0f) invDt0 = step.invDt
     lock = false</diff>
      <filename>scalabox2d/src/main/scala/org/villane/box2d/dynamics/World.scala</filename>
    </modified>
    <modified>
      <diff>@@ -5,24 +5,54 @@ import vecmath.Preamble._
 
 import collection.Set
 
+/**
+ * Base trait for controllers.
+ * Controllers are a convience for encapsulating common per-step functionality.
+ */
 trait Controller {
 
+  /** The list of bodies that this controller applies to. */
   def bodies: Set[Body]
 
+  /** This is called on each world step after updating contacts. */
   def step(step: TimeStep)
 
+  /** Iterate over awake bodies. */
   protected def forAwakeBodies(f: Body =&gt; Unit) =
     for (body &lt;- bodies) if (!body.isSleeping) f(body)
 
 }
 
+/**
+ * Controllers should mix this in if they don't have their own body list but
+ * want to rely on contacts generated by 
+ */
 trait SensorManagedBodies extends Controller {
-  var sensor: Body = null
-  def bodies: Set[Body] = Set() ++ 
-    // Filter edges with no actual contacts
-    sensor.contactList filter { !_.contact.manifolds.isEmpty } map { _.other }
+
+  // TODO make this immutable when Scala supports trait params
+  private[this] var _sensor: Body = null
+  /**
+   * The sensor body that owns this controller. If the sensor is destoryed,
+   * the controller is destroyed too.
+   */
+  def sensor = _sensor
+  def sensor_=(body: Body) = {
+    if (_sensor != null) _sensor.dependentControllers -= this
+    _sensor = body
+    if (_sensor != null) _sensor.dependentControllers += this
+  }
+
+  def bodies: Set[Body] =
+    if (_sensor == null)
+      Set()
+    else
+      Set() ++ _sensor.contactList filter (!_.contact.manifolds.isEmpty) map (_.other)
+
 }
 
+/**
+ * Controllers should mix this in if they manage their own list of bodies.
+ */
 trait SelfManagedBodies extends Controller {
 
   private[this] val _bodies = collection.mutable.Set[Body]()
@@ -31,10 +61,12 @@ trait SelfManagedBodies extends Controller {
 
   def addBody(body: Body) = {
     _bodies += body
+    body.managingControllers += this
   }
 
   def removeBody(body: Body) = {
     _bodies -= body
+    body.managingControllers -= this
   }
 
-}
\ No newline at end of file
+}</diff>
      <filename>scalabox2d/src/main/scala/org/villane/box2d/dynamics/controllers/Controller.scala</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>0737bde71cf1acaaabf3c8473228e711b8e1c45c</id>
    </parent>
  </parents>
  <author>
    <name>Erkki Lindpere</name>
    <email>villane@gmail.com</email>
  </author>
  <url>http://github.com/Villane/scalabox2d/commit/6ad24887524719a8128cd0ef219512856d4e0f1e</url>
  <id>6ad24887524719a8128cd0ef219512856d4e0f1e</id>
  <committed-date>2009-06-23T19:15:45-07:00</committed-date>
  <authored-date>2009-06-23T19:15:45-07:00</authored-date>
  <message>Implemented SelfManagedBodies controllers (not tested)</message>
  <tree>f33e5dd5609e34bf7b6c4448d7878f8cd476eb57</tree>
  <committer>
    <name>Erkki Lindpere</name>
    <email>villane@gmail.com</email>
  </committer>
</commit>
