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

[Merged by Bors] - untyped APIs for components and resources #4447

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d0d8d37
bevy_ecs: untyped API to access components
jakobhellermann Jan 27, 2022
ae98499
bevy_ecs: untyped API to access resources
jakobhellermann Apr 9, 2022
d13bbe5
validate nonsend correctness for dynamic resource APIs
jakobhellermann Apr 9, 2022
497685c
bevy_ecs: add insert_resource_by_id
jakobhellermann Apr 9, 2022
9bcbcae
bevy_ecs: untyped API to init components
jakobhellermann Apr 9, 2022
612fd92
bevy_ecs: add Components::iter
jakobhellermann Apr 7, 2022
64f81af
remove TypeId and is_send_and_sync from ComponentDescriptor::new_with…
jakobhellermann Apr 10, 2022
3201c1a
add docs
jakobhellermann Apr 10, 2022
3493688
add tests
jakobhellermann Apr 10, 2022
0dc2f4c
add #[inline]
jakobhellermann Apr 10, 2022
6efc899
two more safety comments
jakobhellermann Apr 10, 2022
1698a7b
fix broken link
jakobhellermann Apr 10, 2022
1db081f
move methods in separate `impl` block so rustdoc deprioritizes them,
jakobhellermann Apr 12, 2022
77c8235
move warning notes to second paragraph
jakobhellermann Apr 19, 2022
720e60b
move resource_by_id methods on world to separate impl block
jakobhellermann Apr 19, 2022
f0280d7
add test for ComponentDescriptor::new_with_layout
jakobhellermann Apr 19, 2022
ce2b0d0
add World::remove_resource_by_id
jakobhellermann Apr 19, 2022
a3f2c6d
add some #[inline] attributes
jakobhellermann Apr 19, 2022
7b6045a
Merge branch 'main' into bevy-ecs-dynamic
jakobhellermann May 1, 2022
974075d
use Ptr types
jakobhellermann May 1, 2022
06de78c
use UnsafeCellDeref::deref_mut
jakobhellermann May 2, 2022
5fa60ef
trigger CI
jakobhellermann May 3, 2022
b2a3fb8
Merge branch 'main' into bevy-ecs-dynamic
jakobhellermann May 3, 2022
1253338
add missing function
jakobhellermann May 3, 2022
b9263ae
Merge branch 'main' into bevy-ecs-dynamic
jakobhellermann May 7, 2022
5bd27d7
Merge branch 'main' into bevy-ecs-dynamic
jakobhellermann May 9, 2022
396d437
add world.get_by_id and world.get_mut_by_id
jakobhellermann May 9, 2022
faac9f4
validate ComponentIds before passing them to unsafe functions expecti…
jakobhellermann May 9, 2022
6051bc7
clean up docs
jakobhellermann May 13, 2022
756d009
cargo fmt
jakobhellermann May 17, 2022
cc784d2
Update crates/bevy_ecs/src/change_detection.rs
jakobhellermann May 17, 2022
b22ec5a
change EntityRef::get_by_id to return 'w ptr, like its typed variant
jakobhellermann May 17, 2022
b02170a
Merge branch 'main' into bevy-ecs-dynamic
jakobhellermann May 17, 2022
041688e
update to optional drop pointer in ComponentDescriptor
jakobhellermann May 17, 2022
3965a1b
Merge branch 'main' into bevy-ecs-dynamic
jakobhellermann May 24, 2022
9547a9b
fix new_with_layout constructor in test
jakobhellermann May 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add world.get_by_id and world.get_mut_by_id
  • Loading branch information
jakobhellermann committed May 9, 2022
commit 396d4377d7a00bc3350c690a68feda2b5b6bcabc
41 changes: 26 additions & 15 deletions crates/bevy_ecs/src/world/entity_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,30 +527,20 @@ impl<'w> EntityMut<'w> {
/// which is only valid while the [`EntityMut`] is alive.
#[inline]
pub fn get_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
// SAFE: world access is unique and entity location is valid
unsafe {
get_component_and_ticks(self.world, component_id, self.entity, self.location).map(
|(value, ticks)| MutUntyped {
value: value.assert_unique(),
ticks: Ticks {
component_ticks: ticks.deref_mut(),
last_change_tick: self.world.last_change_tick(),
change_tick: self.world.read_change_tick(),
},
},
)
}
// SAFE: entity location is valid
unsafe { get_mut_by_id(self.world, self.entity, self.location, component_id) }
}
}

// TODO: move to Storages?
/// Get a raw pointer to a particular [`Component`] on a particular [`Entity`] in the provided [`World`].
///
/// # Safety
/// `entity_location` must be within bounds of the given archetype and `entity` must exist inside
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
/// the archetype
/// - `component_id` must be valid
#[inline]
unsafe fn get_component(
pub(crate) unsafe fn get_component(
world: &World,
component_id: ComponentId,
entity: Entity,
Expand Down Expand Up @@ -871,6 +861,27 @@ pub(crate) unsafe fn get_mut<T: Component>(
)
}

// SAFETY: EntityLocation must be valid, component_id must be valid
#[inline]
pub(crate) unsafe fn get_mut_by_id(
world: &mut World,
entity: Entity,
location: EntityLocation,
component_id: ComponentId,
) -> Option<MutUntyped> {
// SAFE: world access is unique and entity location is valid
get_component_and_ticks(world, component_id, entity, location).map(|(value, ticks)| {
MutUntyped {
value: value.assert_unique(),
ticks: Ticks {
component_ticks: ticks.deref_mut(),
last_change_tick: world.last_change_tick(),
change_tick: world.read_change_tick(),
},
}
})
}

#[cfg(test)]
mod tests {
use crate as bevy_ecs;
Expand Down
40 changes: 40 additions & 0 deletions crates/bevy_ecs/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,46 @@ impl World {

Some(())
}

/// Retrieves a mutable untyped reference to the given `entity`'s [Component] of the given [`ComponentId`].
/// Returns [None] if the `entity` does not have a [Component] of the given type.
///
/// **You should prefer to use the typed API [`World::get_mut`] where possible and only
/// use this in cases where the actual types are not known at compile time.**
#[inline]
pub fn get_by_id(&self, entity: Entity, component_id: ComponentId) -> Option<Ptr<'_>> {
// SAFE: entity location is valid
unsafe {
get_component(
self,
component_id,
entity,
self.get_entity(entity)?.location(),
)
}
}

/// Retrieves a mutable untyped reference to the given `entity`'s [Component] of the given [`ComponentId`].
/// Returns [None] if the `entity` does not have a [Component] of the given type.
///
/// **You should prefer to use the typed API [`World::get_mut`] where possible and only
/// use this in cases where the actual types are not known at compile time.**
#[inline]
pub fn get_mut_by_id(
&mut self,
entity: Entity,
component_id: ComponentId,
) -> Option<MutUntyped<'_>> {
// SAFE: entity location is valid
unsafe {
get_mut_by_id(
self,
entity,
self.get_entity(entity)?.location(),
component_id,
)
}
}
}

impl fmt::Debug for World {
Expand Down