I've often found myself wanting to run the same system code on the same query data, but in more than one possible combination of change detection filters. To avoid an impending XY problem, this usually happens when:
- I have one bit of state (such as a UI 'view') that is tracking another bit of state (the 'model', I guess);
- One of the change detection filter sets is firing the system once when the 'view' is created, to set the initial state;
- The other one is firing the system every time the 'model' is updated, to update the state;
- The queries being filtered are disjoint (meaning I can't just use
Or).
A random example from a bit of tile editor UI code:
pub(super) fn backpropagate_pixel_states<C: QueryFilter, P: QueryFilter>(
buffer: Single<&MainBuffer, C>, // model: some buffer containing pixel data
mut pixels: Query<&mut Pixel, P>, // view: some UI elements displaying individual pixel values
) {
// ...
}
// in the plugin:
app.add_systems(Update, (
systems::backpropagate_pixel_states::<(), Added<Pixel>>,
systems::backpropagate_pixel_states::<Changed<MainBuffer>, ()>,
))
This works, but feels clunky, and makes me wonder whether there is either a more obvious way to handle these kinds of 'use a system in multiple different ways' (maybe not using change detection filters), or whether it's entirely an anti-pattern and I should be breaking this up in a different way (using observers or events, etc).
Any pointers would be very helpful!
Thanks!