bevy
bevy copied to clipboard
bevy_ecs: add untyped methods for inserting components and bundles
This MR is a rebased and alternative proposal to https://github.com/bevyengine/bevy/pull/5602
Objective
- https://github.com/bevyengine/bevy/pull/4447 implemented untyped (using component ids instead of generics and TypeId) APIs for inserting/accessing resources and accessing components, but left inserting components for another PR (this one)
Solution
-
add
EntityMut::insert_by_id
-
split
Bundle
intoDynamicBundle
withget_components
andBundle: DynamicBundle
. This allows theBundleInserter
machinery to be reused for bundles that can only be written, not read, and have no statically availableComponentIds
-
Compared to the original MR this approach exposes unsafe endpoints and requires the user to manage instantiated
BundleIds
. This is quite easy for the end user to do and does not incur the performance penalty of checking whether component input is correctly provided for theBundleId
. -
This MR does ensure that constructing
BundleId
itself is safe
Changelog
- add methods for inserting bundles and components to:
world.entity_mut(entity).insert_by_id
I like it! Needs more docs though.
Controversial because we need to decide between this and https://github.com/bevyengine/bevy/pull/5602.
Thanks for the review @jakobhellermann @james7132!
I made the following changes to address your review comments:
-
init_dynamic_info
now caches dynamic bundles and only verifies component existence when creating new bundles. -
init_dynamic_info
caches into two hash maps, one for dynamic length bundles and the single component bundle case (additionally caching the storage type). - Added
insert_by_id
which only takesComponentId
, turned out very nicely -
insert_bundle_by_id
now doesn't require the storage type - Added
insert_bundle_by_id_unchecked
which is used byinsert_by_id
andinsert_bundle_by_id
but is also available to be used publicly (as it skips an allocation).
I like the new changes a lot; this is a much friendlier API now.
Now that I think about it init_dynamic_info
is quite cheap to call so I could get away with creating API that doesn't expose BundleId
.
Worked like a charm, only insert_by_id
and insert_bundle_by_id
are retained as public APIs.
The only drawback is I had to cache the storage types of bundle components, this seems relatively innocuous but can be relatively easily removed.
Rebased PR
Renamed insert_bundle_by_id
to insert_by_ids