Skip to content

Add an inverse to Changed and Added filters #7265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
nicopap opened this issue Jan 18, 2023 · 5 comments
Open

Add an inverse to Changed and Added filters #7265

nicopap opened this issue Jan 18, 2023 · 5 comments
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible D-Complex Quite challenging from either a design or technical perspective. Ask for help!

Comments

@nicopap
Copy link
Contributor

nicopap commented Jan 18, 2023

Allows exclusive access based on Changed or Added component, similar to With and Without.

See #7264 (comment)

This is very niche, but might help squeeze out some perfs.

What solution would you like?

Add a NotChanged<T> and NotAdded<T> component that returns all entities that their Changed and Added counterparts do not return.

Am I missing something? It seems possible to discriminate based on those filters. Though it would likely require modifying the AccessSet content.

What alternative(s) have you considered?

I added a changed: Query<(), Changed<Transform>> parameter, and call !changed.contains(&entity).

Additional context

@nicopap nicopap added C-Feature A new feature, making something new possible A-ECS Entities, components, systems, and events labels Jan 18, 2023
@djeedai
Copy link
Contributor

djeedai commented Jan 18, 2023

Should we consider a generic Not<>? I don't know how feasible this is though.

@james7132
Copy link
Member

james7132 commented Jan 18, 2023

Should we consider a generic Not<>? I don't know how feasible this is though.

Probably would just be a simple Not<T: ReadOnlyWorldQuery> that just inverts the output on filter_fetch. It probably should be noted that it wouldn't be an archetypal filter and would run against the split between With/Without.

@james7132 james7132 added the S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it! label Jan 18, 2023
@CatThingy
Copy link
Contributor

I took a stab at Not<T> in #7271, but ran into some issues I could not resolve. matches_component_set has different "negation behaviours" for With(out) and Added/Changed: for With(out), it must be negated; for Added/Changed, it must not be. If individual implementations were implemented for the four "inner" filters, Or then becomes impossible to generically negate as it's possible to mix With(out) and Added/Changed within an Or. One possible solution moving forward is to have an additional trait that defines the negation behaviour.

My implementation also had Not<Added<T>> imply With<T>, which is not a logical negation of Added<T>.

@alice-i-cecile alice-i-cecile added D-Complex Quite challenging from either a design or technical perspective. Ask for help! and removed S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it! labels Feb 27, 2023
@ickk
Copy link
Contributor

ickk commented Aug 10, 2023

As a user-story, today I tried to do something like the following in order to filter out all the entities that had a component added in the same frame.

Query<&T, Without<Added<T>>>

I was somewhat surprised that this was not supported.


Having set-like operations defined on Query could also be useful to solve similar problems instead with run-time compositions, i.e.

fn system(
  a: Query<Entity>
  b: Query<Added<&T>
) {
  // set difference; C is the set of all entities that satisfy A but 
  // with the entities that satisfy B removed
  let c: Query<Entity> = a - b;
}

@maniwani
Copy link
Contributor

NotChanged<T> and NotAdded<T> return all entities that Changed<T> and Added<T> do not.

Changed<T> and Added<T> have an implicit With<T>. Inverting their output won't change that. They'll return the entities that have a T that wasn't recently changed or added. Their inverses should not include entities matched by Without<T>.

My implementation also had Not<Added<T>> imply With<T>, which is not a logical negation of Added<T>.

This would be much clearer if Added<T> and is_added were named New<T> and is_new (which is what it means). IMO if you ask for "entities whose T is not new", it doesn't make any sense to include entities that don't even have T.

It's not the complementary set of entities, but the implied With<T> is intuitive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible D-Complex Quite challenging from either a design or technical perspective. Ask for help!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants