Open z33ky opened 6 years ago
I see the limitation here. Filling a Vec<ColliderIndex>
seems to be the cleanest way to do this with the current implementation.
The issue with your proposal is that BroadPhase::update_with_callback_parameter<Parameter>
will make the BroadPhase
impossible to use as a trait-object because it takes a type parameter. I'm not sure what other solution would be viable (besides passing a &mut Box
which is ugly).
This could be solved well by replacing the two callbacks with a trait object:
trait BroadPhaseFilter<T> {
fn allow_proximity(&mut self, &T, &T) -> bool;
fn proximity_handler(&mut self, &T, &T, bool);
}
trait BroadPhase<T> {
fn update(&mut self, &mut BroadPhaseFilter<T>);
}
A mutable reference can safely be stored inside an implementer and used in both methods.
Alternatively, to reduce boilerplate, a single callback could be used, taking a parameter that tells it which behavior is desired for any given invocation. The trait object approach seems less confusing to me, though.
Thanks @Ralith ! The trait-object based approach seems to be the right approach.
BroadPhase::update
takes two callback-functions,allow_proximity
andproximity_handler
. In my code I am not storing the objects themselves in theBroadPhase
, but indices to them (I have a minified version here). I am unable to obtain the actual objects from the indices in both callbacks if one is mutable, since Rust only allows a singular mutable reference. The problem in the minified code is at line 81, whereentities
is borrowed mutably for theproximity_handler
and immutably for theallow_proximity
. I could use aRefCell
,unsafe
or pass an immutable reference to both and fill aVec<ColliderIndex>
inWorld::collide
to actually handle collisions afterwards, but I think this could be solved by providing amethod, which passes
param
to both callbacks. Line 81 in the minified example would becomewithout violating borrow checks.
BroadPhase::update
can simply be implemented via.
Now when three circles collide as the same time, it will depend on the evaluation order which two circles die and which is kept alive, but this is just some example code anyways.
allow_proximity
could also take a&mut Parameter
instead of&Parameter
, just for my specific use-case,allow_proximity
only needs a immutable reference. It would likely depend on whatParameter
actually is to determine whether it should be mutable or not, though aFnMut(&Parameter, &T, &T)
can be implicitly converted to aFnMut(&mut Parameter, &T, &T)
. I like to prevent "accidental mutability" though; A separateupdate_with_callback_parameter_mutable_allow
-method can be added andupdate_with_callback_parameter
can call that. A better name would be desirable.