Dart Documentationbox2d_consoleContactManager

ContactManager class

class ContactManager implements PairCallback {
  BroadPhase broadPhase;
  Contact contactList;
  int contactCount;
  ContactFilter contactFilter;
  ContactListener contactListener;

  final World pool;

  ContactManager(World argPool) :
    contactList = null,
    contactCount = 0,
    contactFilter = new ContactFilter(),
    contactListener = null,
    broadPhase = new BroadPhase(),
    pool = argPool { }

  /**
   * Broad-phase callback.
   */
  void addPair(Fixture fixtureA, Fixture fixtureB) {
    Body bodyA = fixtureA.body;
    Body bodyB = fixtureB.body;

    // Are the fixtures on the same body?
    if (bodyA === bodyB) {
      return;
    }

    // Does a contact already exist?
    ContactEdge edge = bodyB.contactList;
    while (edge != null) {
      if (edge.other == bodyA) {
        Fixture fA = edge.contact.fixtureA;
        Fixture fB = edge.contact.fixtureB;
        if (fA == fixtureA && fB == fixtureB) {
          // A contact already exists.
          return;
        }

        if (fA == fixtureB && fB == fixtureA) {
          // A contact already exists.
          return;
        }
      }

      edge = edge.next;
    }

    // Does a joint override collision? is at least one body dynamic?
    if (bodyB.shouldCollide(bodyA) == false) {
      return;
    }

    // Check user filtering.
    if (contactFilter != null && 
        contactFilter.shouldCollide(fixtureA, fixtureB) == false) {
      return;
    }

    // Call the factory.
    Contact c = pool.popContact(fixtureA, fixtureB);

    // Contact creation may swap fixtures.
    fixtureA = c.fixtureA;
    fixtureB = c.fixtureB;
    bodyA = fixtureA.body;
    bodyB = fixtureB.body;

    // Insert into the world.
    c.prev = null;
    c.next = contactList;
    if (contactList != null) {
      contactList.prev = c;
    }
    contactList = c;

    // Connect to island graph.

    // Connect to body A
    c.edge1.contact = c;
    c.edge1.other = bodyB;

    c.edge1.prev = null;
    c.edge1.next = bodyA.contactList;
    if (bodyA.contactList != null) {
      bodyA.contactList.prev = c.edge1;
    }
    bodyA.contactList = c.edge1;

    // Connect to body B
    c.edge2.contact = c;
    c.edge2.other = bodyA;

    c.edge2.prev = null;
    c.edge2.next = bodyB.contactList;
    if (bodyB.contactList != null)
      bodyB.contactList.prev = c.edge2;
    bodyB.contactList = c.edge2;

    ++contactCount;
  }

  void findNewContacts() { broadPhase.updatePairs(this); }

  void destroy(Contact c) {
    Fixture fixtureA = c.fixtureA;
    Fixture fixtureB = c.fixtureB;
    Body bodyA = fixtureA.body;
    Body bodyB = fixtureB.body;

    if (contactListener != null && c.touching) {
      contactListener.endContact(c);
    }

    // Remove from the world.
    if (c.prev != null)
      c.prev.next = c.next;

    if (c.next != null)
      c.next.prev = c.prev;

    if (c == contactList)
      contactList = c.next;

    // Remove from body 1
    if (c.edge1.prev != null)
      c.edge1.prev.next = c.edge1.next;

    if (c.edge1.next != null)
      c.edge1.next.prev = c.edge1.prev;

    if (c.edge1 == bodyA.contactList)
      bodyA.contactList = c.edge1.next;

    // Remove from body 2
    if (c.edge2.prev != null)
      c.edge2.prev.next = c.edge2.next;

    if (c.edge2.next != null)
      c.edge2.next.prev = c.edge2.prev;

    if (c.edge2 == bodyB.contactList)
      bodyB.contactList = c.edge2.next;

    // Call the factory.
    pool.pushContact(c);
    --contactCount;
  }

  /**
   * This is the top level collision call for the time step. Here
   * all the narrow phase collision is processed for the world
   * contact list.
   */
  void collide() {
    // Update awake contacts.
    Contact c = contactList;
    while (c != null) {
      Fixture fixtureA = c.fixtureA;
      Fixture fixtureB = c.fixtureB;
      Body bodyA = fixtureA.body;
      Body bodyB = fixtureB.body;


      if (bodyA.awake == false && bodyB.awake == false) {
        c = c.next;
        continue;
      }

      // is this contact flagged for filtering?
      if ((c.flags & Contact.FILTER_FLAG) == Contact.FILTER_FLAG) {
        // Should these bodies collide?
        if (bodyB.shouldCollide(bodyA) == false) {
          Contact cNuke = c;
          c = cNuke.next;
          destroy(cNuke);
          continue;
        }

        // Check user filtering.
        if (contactFilter != null &&
            contactFilter.shouldCollide(fixtureA, fixtureB) == false) {
          Contact cNuke = c;
          c = cNuke.next;
          destroy(cNuke);
          continue;
        }

        // Clear the filtering flag.
        c.flags &= ~Contact.FILTER_FLAG;
      }

      DynamicTreeNode proxyIdA = fixtureA.proxy;
      DynamicTreeNode proxyIdB = fixtureB.proxy;

      bool overlap = broadPhase.testOverlap(proxyIdA, proxyIdB);

      // Here we destroy contacts that cease to overlap in the broad-phase.
      if (overlap == false) {
        Contact cNuke = c;
        c = cNuke.next;
        destroy(cNuke);
        continue;
      }

      // The contact persists.
      c.update(contactListener);
      c = c.next;
    }
  }
}

Implements

PairCallback

Constructors

new ContactManager(World argPool) #

ContactManager(World argPool) :
  contactList = null,
  contactCount = 0,
  contactFilter = new ContactFilter(),
  contactListener = null,
  broadPhase = new BroadPhase(),
  pool = argPool { }

Properties

BroadPhase broadPhase #

BroadPhase broadPhase;

int contactCount #

int contactCount;

ContactFilter contactFilter #

ContactFilter contactFilter;

Contact contactList #

Contact contactList;

ContactListener contactListener #

ContactListener contactListener;

final World pool #

final World pool;

final Type runtimeType #

inherited from Object

A representation of the runtime type of the object.

external Type get runtimeType;

Operators

bool operator ==(other) #

inherited from Object

The equality operator.

The default behavior for all Objects is to return true if and only if this and other are the same object.

If a subclass overrides the equality operator it should override the hashCode method as well to maintain consistency.

bool operator ==(other) => identical(this, other);

Methods

void addPair(Fixture fixtureA, Fixture fixtureB) #

Broad-phase callback.

void addPair(Fixture fixtureA, Fixture fixtureB) {
  Body bodyA = fixtureA.body;
  Body bodyB = fixtureB.body;

  // Are the fixtures on the same body?
  if (bodyA === bodyB) {
    return;
  }

  // Does a contact already exist?
  ContactEdge edge = bodyB.contactList;
  while (edge != null) {
    if (edge.other == bodyA) {
      Fixture fA = edge.contact.fixtureA;
      Fixture fB = edge.contact.fixtureB;
      if (fA == fixtureA && fB == fixtureB) {
        // A contact already exists.
        return;
      }

      if (fA == fixtureB && fB == fixtureA) {
        // A contact already exists.
        return;
      }
    }

    edge = edge.next;
  }

  // Does a joint override collision? is at least one body dynamic?
  if (bodyB.shouldCollide(bodyA) == false) {
    return;
  }

  // Check user filtering.
  if (contactFilter != null && 
      contactFilter.shouldCollide(fixtureA, fixtureB) == false) {
    return;
  }

  // Call the factory.
  Contact c = pool.popContact(fixtureA, fixtureB);

  // Contact creation may swap fixtures.
  fixtureA = c.fixtureA;
  fixtureB = c.fixtureB;
  bodyA = fixtureA.body;
  bodyB = fixtureB.body;

  // Insert into the world.
  c.prev = null;
  c.next = contactList;
  if (contactList != null) {
    contactList.prev = c;
  }
  contactList = c;

  // Connect to island graph.

  // Connect to body A
  c.edge1.contact = c;
  c.edge1.other = bodyB;

  c.edge1.prev = null;
  c.edge1.next = bodyA.contactList;
  if (bodyA.contactList != null) {
    bodyA.contactList.prev = c.edge1;
  }
  bodyA.contactList = c.edge1;

  // Connect to body B
  c.edge2.contact = c;
  c.edge2.other = bodyA;

  c.edge2.prev = null;
  c.edge2.next = bodyB.contactList;
  if (bodyB.contactList != null)
    bodyB.contactList.prev = c.edge2;
  bodyB.contactList = c.edge2;

  ++contactCount;
}

void collide() #

This is the top level collision call for the time step. Here all the narrow phase collision is processed for the world contact list.

void collide() {
  // Update awake contacts.
  Contact c = contactList;
  while (c != null) {
    Fixture fixtureA = c.fixtureA;
    Fixture fixtureB = c.fixtureB;
    Body bodyA = fixtureA.body;
    Body bodyB = fixtureB.body;


    if (bodyA.awake == false && bodyB.awake == false) {
      c = c.next;
      continue;
    }

    // is this contact flagged for filtering?
    if ((c.flags & Contact.FILTER_FLAG) == Contact.FILTER_FLAG) {
      // Should these bodies collide?
      if (bodyB.shouldCollide(bodyA) == false) {
        Contact cNuke = c;
        c = cNuke.next;
        destroy(cNuke);
        continue;
      }

      // Check user filtering.
      if (contactFilter != null &&
          contactFilter.shouldCollide(fixtureA, fixtureB) == false) {
        Contact cNuke = c;
        c = cNuke.next;
        destroy(cNuke);
        continue;
      }

      // Clear the filtering flag.
      c.flags &= ~Contact.FILTER_FLAG;
    }

    DynamicTreeNode proxyIdA = fixtureA.proxy;
    DynamicTreeNode proxyIdB = fixtureB.proxy;

    bool overlap = broadPhase.testOverlap(proxyIdA, proxyIdB);

    // Here we destroy contacts that cease to overlap in the broad-phase.
    if (overlap == false) {
      Contact cNuke = c;
      c = cNuke.next;
      destroy(cNuke);
      continue;
    }

    // The contact persists.
    c.update(contactListener);
    c = c.next;
  }
}

new ContactManager(World argPool) #

ContactManager(World argPool) :
  contactList = null,
  contactCount = 0,
  contactFilter = new ContactFilter(),
  contactListener = null,
  broadPhase = new BroadPhase(),
  pool = argPool { }

void destroy(Contact c) #

void destroy(Contact c) {
  Fixture fixtureA = c.fixtureA;
  Fixture fixtureB = c.fixtureB;
  Body bodyA = fixtureA.body;
  Body bodyB = fixtureB.body;

  if (contactListener != null && c.touching) {
    contactListener.endContact(c);
  }

  // Remove from the world.
  if (c.prev != null)
    c.prev.next = c.next;

  if (c.next != null)
    c.next.prev = c.prev;

  if (c == contactList)
    contactList = c.next;

  // Remove from body 1
  if (c.edge1.prev != null)
    c.edge1.prev.next = c.edge1.next;

  if (c.edge1.next != null)
    c.edge1.next.prev = c.edge1.prev;

  if (c.edge1 == bodyA.contactList)
    bodyA.contactList = c.edge1.next;

  // Remove from body 2
  if (c.edge2.prev != null)
    c.edge2.prev.next = c.edge2.next;

  if (c.edge2.next != null)
    c.edge2.next.prev = c.edge2.prev;

  if (c.edge2 == bodyB.contactList)
    bodyB.contactList = c.edge2.next;

  // Call the factory.
  pool.pushContact(c);
  --contactCount;
}

void findNewContacts() #

void findNewContacts() { broadPhase.updatePairs(this); }

int hashCode() #

inherited from Object

Get a hash code for this object.

All objects have hash codes. Hash codes are guaranteed to be the same for objects that are equal when compared using the equality operator ==. Other than that there are no guarantees about the hash codes. They will not be consistent between runs and there are no distribution guarantees.

If a subclass overrides hashCode it should override the equality operator as well to maintain consistency.

external int hashCode();

noSuchMethod(String name, List args) #

inherited from Object

noSuchMethod is invoked when users invoke a non-existant method on an object. The name of the method and the arguments of the invocation are passed to noSuchMethod. If noSuchMethod returns a value, that value becomes the result of the original invocation.

The default behavior of noSuchMethod is to throw a noSuchMethodError.

external Dynamic noSuchMethod(String name, List args);

const Object() #

inherited from Object

Creates a new Object instance.

Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.

const Object();

String toString() #

inherited from Object

Returns a string representation of this object.

external String toString();