Add SystemIdTemplate to allow one-shot system in bsn!#24026
Add SystemIdTemplate to allow one-shot system in bsn!#24026hxYuki wants to merge 5 commits intobevyengine:mainfrom
SystemIdTemplate to allow one-shot system in bsn!#24026Conversation
|
Welcome, new contributor! Please make sure you've read our contributing guide, as well as our policy regarding AI usage, and we look forward to reviewing your pull request shortly ✨ |
|
Not sure where to place these codes. I've searched |
|
|
||
| impl Default for SystemIdTemplate { | ||
| fn default() -> Self { | ||
| Self::BoxedSystem(Arc::new(Mutex::new(Some(Box::new(IntoSystem::into_system(|| {})))))) |
There was a problem hiding this comment.
What should be the default value for a SystemId?
SkiFire13
left a comment
There was a problem hiding this comment.
IMO this is becoming pretty complex and I'm kinda losing track of how everything fits together.
| let system_refs_entity = world.get::<RefToSystem>(entity).unwrap().0; | ||
| let system_refs = &world.get::<SystemRefs>(system_refs_entity).unwrap().0; | ||
|
|
||
| if system_refs.is_empty() { // a system is no more referenced, so we can clean it up. |
There was a problem hiding this comment.
I don't think this is guaranteed to run after relationship has been removed from SystemRefs
There was a problem hiding this comment.
Relationship connection is maintained in on_discard and this happens in on_remove.
As documented in lifecycle.rs:
An
on_discardhook always runs before anyon_removehooks (if the component is being removed from the entity).
Relationship must have already been removed before this hook.
There was a problem hiding this comment.
Makes sense, I would document it here though.
|
|
||
| /// These are used to track one-shot systems registered from templates, so that they can be cleaned up when the template is no longer in use and to prevent duplicate registrations. | ||
| /// | ||
| /// A template instance will create a linked entity for each holding one-shot system. Each system will create a entity with `SytemIdRecorder` saved in `SceneSystemRegistry`, which counting references to it via `RefToSystem`. |
There was a problem hiding this comment.
The CI warning looks legit ("Sytem" instead of "System")
There was a problem hiding this comment.
Yhea, didn't run ci locally yet as drafting.
| #[derive(Resource, Default)] | ||
| struct SceneSystemRegistry { | ||
| type_map: bevy_platform::collections::HashMap<core::any::TypeId, Entity>, | ||
| id_map: bevy_platform::collections::HashMap<SystemId<(), ()>, Entity>, | ||
| } | ||
|
|
||
| #[derive(Component, Clone)] | ||
| struct SystemIdRecorder { | ||
| type_id: core::any::TypeId, | ||
| system_id: SystemId<(), ()>, | ||
| } |
There was a problem hiding this comment.
Even with the documentation it's not clear to me what these are actually doing.
There was a problem hiding this comment.
erDiagram
TemplateEntity ||--o{ MiddleEntity : "link lifetime"
MiddleEntity ||--|{ SystemEntity : "reference count"
SceneSystemRegistry ||--|{ SystemEntity : stores
TemplateBuild }|..|{ SceneSystemRegistry:"check system existence, create relationship"
TemplateEntity {
CallbackComponet systemId
}
MiddleEntity {
LinkLifetimeWith templateEntity
RefToSystem systemEntity
}
SceneSystemRegistry {
Hashmap system_id_map_to_entity
Hashmap type_id_map_to_entity
}
SystemEntity {
SystemId systemId
TypeId systemType
}
It simulates a many-to-many relationship between template and system. It should be a little simpler than it looks if we have many-to-many relationship.
There was a problem hiding this comment.
I can understand MiddleEntity, however SceneSystemRegistry is still unclear.
system_id_map_to_entity looks like it's just the same as SystemId::entity? While type_id_map_to_entity doesn't look correct since there might be different systems with the same type.
There was a problem hiding this comment.
We may get a BoxedSystem or a SystemId on build_template. I need to connect the two "key" together. And a Relatioship targets to an Entity. So I spawn new entities to save these.
I forgot the SystemId has a field. Maybe I can reuse its entity and get the map eliminated.
there might be different systems with the same type.
What is it exactly? I tried fn callback_1(mut call_counter:Local<u32>) and fn callback_2(mut call_counter:Local<u32>), they have different TypeId. And I copied the assertion in World::register_system_cached to system_value, I assumed the TypeId have same mechanism like type parameter.
There was a problem hiding this comment.
fn make_system(a: u32) -> impl System {
bevy_ecs::system::IntoSystem::into_system(move || {
println!("{a}");
})
}make_system(0) and make_system(1) have the same type but are different systems (running them will produce different outputs). In general closures used as systems cause this issue.
register_system_cached has a ZST check precisely to avoid this issue (because ZST systems are always equal).
Objective
Solution
SystemIdTemplateFromTemplateforSystemIdsystem_value<M>to convert a system toSystemIdTemplateTesting
3d_scene.Showcase