Skip to content
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

API to retain bundle components on entities #10865

Closed
iiYese opened this issue Dec 4, 2023 · 1 comment · Fixed by #10873
Closed

API to retain bundle components on entities #10865

iiYese opened this issue Dec 4, 2023 · 1 comment · Fixed by #10873
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it!

Comments

@iiYese
Copy link
Contributor

iiYese commented Dec 4, 2023

What problem does this solve or what need does it fill?

Sometimes we want to remove all components except for a select few from an entity. One use case I've encountered this for is when trying to do events as entities. I want to remove/rest all the data from event entities while keeping the Event markers that annotates the entity is an event entity. This comes up for less experimental use cases too.

What solution would you like?

A fn retain<T: Bundle>(&mut self) -> &mut Self API for EntityWorldMut & EntityCommands.

What alternative(s) have you considered?

let components = world.entity(e).take::<B>().unwrap();
world.despawn(e);
world.get_or_spawn(e).insert(components);

This will only work if the entity has all of the components in B. The retain API should work regardless of if all components in B are present.

@iiYese iiYese added C-Feature A new feature, making something new possible A-ECS Entities, components, systems, and events labels Dec 4, 2023
@alice-i-cecile alice-i-cecile added the S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it! label Dec 4, 2023
@alice-i-cecile
Copy link
Member

Something critical to document: you can pass in () as the Bundle type, and all components will be removed.

github-merge-queue bot pushed a commit that referenced this issue Dec 5, 2023
# Objective
Adds `EntityCommands.retain` and `EntityWorldMut.retain` to remove all
components except the given bundle from the entity.
Fixes #10865.

## Solution

I added a private unsafe function in `EntityWorldMut` called
`remove_bundle_info` which performs the shared behaviour of `remove` and
`retain`, namely taking a `BundleInfo` of components to remove, and
removing them from the given entity. Then `retain` simply gets all the
components on the entity and filters them by whether they are in the
bundle it was passed, before passing this `BundleInfo` into
`remove_bundle_info`.

`EntityCommands.retain` just creates a new type `Retain` which runs
`EntityWorldMut.retain` when run.

---

## Changelog

Added `EntityCommands.retain` and `EntityWorldMut.retain`, which remove
all components except the given bundle from the entity, they can also be
used to remove all components by passing `()` as the bundle.
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 S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants