-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
impl EntityBorrow for more types #16917
impl EntityBorrow for more types #16917
Conversation
entity: Entity, | ||
location: EntityLocation, | ||
pub(crate) world: UnsafeWorldCell<'w>, | ||
pub(crate) entity: Entity, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really necessary to loosen the privacy here?
It looks like this is only needed so you can get an &Entity
instead of an Entity
to impl Borrow<Entity>
for a few types. Since we're no longer using Borrow<Entity>
internally, could we just leave out those impls?
Alternately, could we add a pub (crate)
method to get &Entity
so that it's clear nothing outside of this module modifies these fields?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, there is a much simpler solution: I hadn't thought of just adding an entity
method on UnsafeEntityCell
itself for some reason. Should UnsafeEntityCell
itself implement EntityBorrow
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I remembered why I didn't do this initially. Unless you return &Entity
directly from a field, you will get a temporary lifetime error. So unless we increase the visibility here, or move the UnsafeEntityCell
type to entity_ref.rs
, we cannot impl Borrow<Entity>
for the EntityRef
types.
The reason why I added this impl is for the original purpose of Borrow
: to allow its use in Map
and Set
types.
But I can omit it instead then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it works if the method returns a reference to the original value:
impl UnsafeEntityCell<'_> {
pub(crate) fn entity_ref(&self) -> &Entity {
&self.entity
}
}
impl Borrow<Entity> for EntityMut<'_> {
fn borrow(&self) -> &Entity {
self.0.entity_ref()
}
}
But it's a moot point now that you removed them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahhh, you're right! Had I taken my train of thought just a bit further I could've realized, we can just impl Borrow<Entity>
and EntityBorrow
for UnsafeEntityCell
...
I'll add them back.
@@ -869,6 +919,47 @@ impl<'a> TryFrom<&'a mut FilteredEntityMut<'_>> for EntityMut<'a> { | |||
} | |||
} | |||
|
|||
impl PartialEq for EntityMut<'_> { | |||
fn eq(&self, other: &Self) -> bool { | |||
self.entity() == other.entity() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand why we need to have this, but it's a little amusing since there can't possibly be two EntityMut
s alive for the same entity
. It's also not very useful with Query::iter_many
, since you can never have an EntityMut
that would match the query. Well, it can get combined with this other impls as part of the EntityPtr
work and then it won't seem odd anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You still can have its entity match another query! That is one thing the nesting_queries()
test in entity_set.rs
shows. But it is definitely more obscure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I just meant EntityMut
specifically. It has write access to all components, so it's going to conflict with any other query that matches the same archetypes. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also meant EntityMut
specifically! You can still query for an archetype without accessing any components :)
@@ -386,6 +386,8 @@ impl PartialEq for EntityRef<'_> { | |||
|
|||
impl Eq for EntityRef<'_> {} | |||
|
|||
// We intentionally choose to have EntityRef compare like Entity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose the danger here is that entities from different world
s that happen to have the same ID will compare equal. That seems unlikely to be a problem in practice, although it might be worth documenting somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it is a bit unfortunate that we can't have both entity comparison/world comparison, but it seems to me that being able to compare them like Entity
is a lot more valuable. I think I'll add some documentation to the types themselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! I like seeing gaps in the API filled like this.
# Objective Some types like `RenderEntity` and `MainEntity` are just wrappers around `Entity`, so they should be able to implement `EntityBorrow`/`TrustedEntityBorrow`. This allows using them with `EntitySet` functionality. The `EntityRef` family are more than direct wrappers around `Entity`, but can still benefit from being unique in a collection. ## Solution Implement `EntityBorrow` and `TrustedEntityBorrow` for simple `Entity` newtypes and `EntityRef` types. These impls are an explicit decision to have the `EntityRef` types compare like just `Entity`. `EntityWorldMut` is omitted from this impl, because it explicitly contains a `&mut World` as well, and we do not ever use more than one at a time. Add `EntityBorrow` to the `bevy_ecs` prelude. ## Migration Guide `NormalizedWindowRef::entity` has been replaced with an `EntityBorrow::entity` impl.
Objective
Some types like
RenderEntity
andMainEntity
are just wrappers aroundEntity
, so they should be able to implementEntityBorrow
/TrustedEntityBorrow
. This allows using them withEntitySet
functionality.The
EntityRef
family are more than direct wrappers aroundEntity
, but can still benefit from being unique in a collection.Solution
Implement
EntityBorrow
andTrustedEntityBorrow
for simpleEntity
newtypes andEntityRef
types.These impls are an explicit decision to have the
EntityRef
types compare like justEntity
.EntityWorldMut
is omitted from this impl, because it explicitly contains a&mut World
as well, and we do not ever use more than one at a time.Add
EntityBorrow
to thebevy_ecs
prelude.Migration Guide
NormalizedWindowRef::entity
has been replaced with anEntityBorrow::entity
impl.