You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Unify filtering by id in EntityClonerBuilder (#19977)
# Objective
#19649 introduced new `*_if_new` and `*_by_bundle_id_*` variations to
`EntityClonerBuilder` filtering functionality, which resulted in
increase in method permutations - there are now 8 allow variants to
support various id types and 2 different insert modes.
## Solution
This PR introduces a new trait `FilterableIds` to unify all id types and
their `IntoIterator` implementations, which is somewhat similar to
`WorldEntityFetch`. It supports `TypeId`, `ComponentId` and `BundleId`,
allowing us to reduce the number of `allow` methods to 4: `allow`,
`allow_if_new`, `allow_by_ids`, `allow_by_ids_if_new`. The function
signature is a bit less readable now, but the docs mention types that
can be passed in.
## Testing
All existing tests pass, performance is unchanged.
---------
Co-authored-by: urben1680 <55257931+urben1680@users.noreply.github.com>
/// Marker trait to allow multiple blanket implementations for [`FilterableIds`].
1264
+
pubtraitMarker{}
1265
+
/// Marker struct for [`FilterableIds`] implementation for single-value types.
1266
+
pubstructScalarType{}
1267
+
implMarkerforScalarType{}
1268
+
/// Marker struct for [`FilterableIds`] implementation for [`IntoIterator`] types.
1269
+
pubstructVectorType{}
1270
+
implMarkerforVectorType{}
1271
+
1272
+
/// Defines types of ids that [`EntityClonerBuilder`] can filter components by.
1273
+
#[derive(From)]
1274
+
pubenumFilterableId{
1275
+
Type(TypeId),
1276
+
Component(ComponentId),
1277
+
Bundle(BundleId),
1278
+
}
1279
+
1280
+
impl<'a,T>From<&'aT>forFilterableId
1281
+
where
1282
+
T:Into<FilterableId> + Copy,
1283
+
{
1284
+
#[inline]
1285
+
fnfrom(value:&'aT) -> Self{
1286
+
(*value).into()
1287
+
}
1288
+
}
1289
+
1290
+
/// A trait to allow [`EntityClonerBuilder`] filter by any supported id type and their iterators,
1291
+
/// reducing the number of method permutations required for all id types.
1292
+
///
1293
+
/// The supported id types that can be used to filter components are defined by [`FilterableId`], which allows following types: [`TypeId`], [`ComponentId`] and [`BundleId`].
1294
+
///
1295
+
/// `M` is a generic marker to allow multiple blanket implementations of this trait.
1296
+
/// This works because `FilterableId<M1>` is a different trait from `FilterableId<M2>`, so multiple blanket implementations for different `M` are allowed.
1297
+
/// The reason this is required is because supporting `IntoIterator` requires blanket implementation, but that will conflict with implementation for `TypeId`
1298
+
/// since `IntoIterator` can technically be implemented for `TypeId` in the future.
1299
+
/// Functions like `allow_by_ids` rely on type inference to automatically select proper type for `M` at call site.
1300
+
pubtraitFilterableIds<M:Marker>{
1301
+
/// Takes in a function that processes all types of [`FilterableId`] one-by-one.
Copy file name to clipboardExpand all lines: release-content/migration-guides/entity_cloner_builder_split.md
+10-3Lines changed: 10 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
title: EntityClonerBuilder Split
3
-
pull_requests: [19649]
3
+
pull_requests: [19649, 19977]
4
4
---
5
5
6
6
`EntityClonerBuilder` is now generic and has different methods depending on the generic.
@@ -40,15 +40,15 @@ The methods of the two builder types are different to 0.16 and to each other now
40
40
41
41
## Opt-Out variant
42
42
43
-
- Still offers variants of the `deny` methods which now also includes one with a `BundleId` argument.
43
+
- Still offers variants of the `deny` methods.
44
44
- No longer offers `allow` methods, you need to be exact with denying components.
45
45
- Offers now the `insert_mode` method to configure if components are cloned if they already exist at the target.
46
46
- Required components of denied components are no longer considered. Denying `A`, which requires `B`, does not imply `B` alone would not be useful at the target. So if you do not want to clone `B` too, you need to deny it explicitly. This also means there is no `without_required_components` method anymore as that would be redundant.
47
47
- It is now the other way around: Denying `A`, which is required _by_`C`, will now also deny `C`. This can be bypassed with the new `without_required_by_components` method.
48
48
49
49
## Opt-In variant
50
50
51
-
- Still offers variants of the `allow` methods which now also includes one with a `BundleId` argument.
51
+
- Still offers variants of the `allow` methods.
52
52
- No longer offers `deny` methods, you need to be exact with allowing components.
53
53
- Offers now `allow_if_new` method variants that only clone this component if the target does not contain it. If it does, required components of it will also not be cloned, except those that are also required by one that is actually cloned.
54
54
- Still offers the `without_required_components` method.
@@ -62,6 +62,13 @@ All other methods `EntityClonerBuilder` had in 0.16 are still available for both
62
62
-`clone_behavior` variants
63
63
-`linked_cloning`
64
64
65
+
## Unified id filtering
66
+
67
+
Previously `EntityClonerBuilder` supported filtering by 2 types of ids: `ComponentId` and `TypeId`, the functions taking in `IntoIterator` for them.
68
+
Since now `EntityClonerBuilder` supports filtering by `BundleId` as well, the number of method variations would become a bit too unwieldy.
69
+
Instead, all id filtering methods were unified into generic `deny_by_ids/allow_by_ids(_if_new)` methods, which allow to filter components by
70
+
`TypeId`, `ComponentId`, `BundleId` and their `IntoIterator` variations.
0 commit comments