mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-01 10:38:17 +08:00
83 lines
2.6 KiB
Dart
83 lines
2.6 KiB
Dart
import 'package:box2d_flame/box2d.dart';
|
|
import 'package:flame/box2d/box2d_component.dart';
|
|
|
|
class ContactTypes<T1, T2> {
|
|
// If o1 is, or inherits from, T1 or T2
|
|
bool has(Object o1) => o1 is T1 || o1 is T2;
|
|
bool hasOne(Object o1, Object o2) => has(o1) || has(o2);
|
|
|
|
// Only makes sense to call with objects that you know is in [T1, T2]
|
|
bool inOrder(Object o1, Object o2) => o1 is T1 && o2 is T2;
|
|
|
|
// Remember that this is not symmetric, it checks if the types in `o1` and
|
|
// `o2` are the same or inherits from the types in `other`
|
|
bool match(Object o1, Object o2) =>
|
|
(o1 is T1 && o2 is T2) || (o2 is T1 && o1 is T2);
|
|
}
|
|
|
|
abstract class ContactCallback<Type1, Type2> {
|
|
ContactTypes<Type1, Type2> types = ContactTypes<Type1, Type2>();
|
|
|
|
void begin(Type1 a, Type2 b, Contact contact);
|
|
void end(Type1 a, Type2 b, Contact contact);
|
|
void preSolve(Type1 a, Type2 b, Contact contact, Manifold oldManifold) {}
|
|
void postSolve(Type1 a, Type2 b, Contact contact, ContactImpulse impulse) {}
|
|
}
|
|
|
|
class ContactCallbacks extends ContactListener {
|
|
final List<ContactCallback> _callbacks = [];
|
|
|
|
void register(ContactCallback callback) {
|
|
_callbacks.add(callback);
|
|
}
|
|
|
|
void deregister(ContactCallback callback) {
|
|
_callbacks.remove(callback);
|
|
}
|
|
|
|
void clear() {
|
|
_callbacks.clear();
|
|
}
|
|
|
|
void _maybeCallback(Contact contact, ContactCallback callback, Function f) {
|
|
final Object a = contact.fixtureA.getBody().userData;
|
|
final Object b = contact.fixtureB.getBody().userData;
|
|
final ContactTypes wanted = callback.types;
|
|
|
|
if (wanted.match(a, b) ||
|
|
(wanted.has(BodyComponent) && wanted.hasOne(a, b))) {
|
|
wanted.inOrder(a, b) ? f(a, b, contact) : f(b, a, contact);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void beginContact(Contact contact) =>
|
|
_callbacks.forEach((c) => _maybeCallback(contact, c, c.begin));
|
|
|
|
@override
|
|
void endContact(Contact contact) =>
|
|
_callbacks.forEach((c) => _maybeCallback(contact, c, c.end));
|
|
|
|
@override
|
|
void preSolve(Contact contact, Manifold oldManifold) {
|
|
_callbacks.forEach((c) {
|
|
final void Function(Object, Object, Contact) preSolveAux =
|
|
(Object a, Object b, Contact contact) {
|
|
c.preSolve(a, b, contact, oldManifold);
|
|
};
|
|
_maybeCallback(contact, c, preSolveAux);
|
|
});
|
|
}
|
|
|
|
@override
|
|
void postSolve(Contact contact, ContactImpulse impulse) {
|
|
_callbacks.forEach((c) {
|
|
final void Function(Object, Object, Contact) postSolveAux =
|
|
(Object a, Object b, Contact contact) {
|
|
c.postSolve(a, b, contact, impulse);
|
|
};
|
|
_maybeCallback(contact, c, postSolveAux);
|
|
});
|
|
}
|
|
}
|