Skip to content

Commit db52552

Browse files
committed
SystemBuilder: better handling of system creation with non-default kind while deferred
kind_id() checks for existing phases and removes them, but the addition of the default OnUpdate phase has not been processed yet by that point (if deferred). Special case for existing entities being passed in, because they effectively have the same issue; the system builder cannot reliably know whether a kind is going to be set on the existing entity in the next defer flush.
1 parent a8be639 commit db52552

File tree

2 files changed

+46
-29
lines changed

2 files changed

+46
-29
lines changed

flecs_ecs/src/addons/system/system_builder.rs

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ where
1313
pub(crate) desc: sys::ecs_system_desc_t,
1414
term_builder: TermBuilder,
1515
world: WorldRef<'a>,
16+
/// Skip setting default phase (`OnUpdate`) if `kind` was set,
17+
/// or an existing entity was passed in (via [`Self::new_from_desc`])
18+
kind_set: bool,
1619
_phantom: core::marker::PhantomData<&'a T>,
1720
}
1821

@@ -26,23 +29,14 @@ where
2629
desc: Default::default(),
2730
term_builder: TermBuilder::default(),
2831
world: world.into(),
32+
kind_set: false,
2933
_phantom: core::marker::PhantomData,
3034
};
3135

3236
obj.desc.entity = unsafe { sys::ecs_entity_init(obj.world_ptr_mut(), &Default::default()) };
3337

3438
T::populate(&mut obj);
3539

36-
#[cfg(feature = "flecs_pipeline")]
37-
unsafe {
38-
sys::ecs_add_id(
39-
world.world_ptr_mut(),
40-
obj.desc.entity,
41-
ecs_dependson(ECS_ON_UPDATE),
42-
);
43-
sys::ecs_add_id(world.world_ptr_mut(), obj.desc.entity, ECS_ON_UPDATE);
44-
}
45-
4640
obj
4741
}
4842

@@ -51,26 +45,20 @@ where
5145
desc,
5246
term_builder: TermBuilder::default(),
5347
world: world.into(),
48+
kind_set: false,
5449
_phantom: core::marker::PhantomData,
5550
};
5651

5752
if obj.desc.entity == 0 {
5853
obj.desc.entity =
5954
unsafe { sys::ecs_entity_init(obj.world_ptr_mut(), &Default::default()) };
55+
} else {
56+
// Can't make assumptions about the kind on an existing entity.
57+
obj.kind_set = true;
6058
}
6159

6260
T::populate(&mut obj);
6361

64-
#[cfg(feature = "flecs_pipeline")]
65-
unsafe {
66-
sys::ecs_add_id(
67-
world.world_ptr_mut(),
68-
obj.desc.entity,
69-
ecs_dependson(ECS_ON_UPDATE),
70-
);
71-
sys::ecs_add_id(world.world_ptr_mut(), obj.desc.entity, ECS_ON_UPDATE);
72-
}
73-
7462
obj
7563
}
7664

@@ -82,6 +70,7 @@ where
8270
desc: Default::default(),
8371
term_builder: TermBuilder::default(),
8472
world: world.into(),
73+
kind_set: false,
8574
_phantom: core::marker::PhantomData,
8675
};
8776

@@ -95,15 +84,6 @@ where
9584

9685
T::populate(&mut obj);
9786

98-
#[cfg(feature = "flecs_pipeline")]
99-
unsafe {
100-
sys::ecs_add_id(
101-
world.world_ptr_mut(),
102-
obj.desc.entity,
103-
ecs_dependson(ECS_ON_UPDATE),
104-
);
105-
sys::ecs_add_id(world.world_ptr_mut(), obj.desc.entity, ECS_ON_UPDATE);
106-
}
10787
obj
10888
}
10989

@@ -134,6 +114,7 @@ where
134114
if phase != 0 {
135115
sys::ecs_add_id(self.world_ptr_mut(), self.desc.entity, ecs_dependson(phase));
136116
sys::ecs_add_id(self.world_ptr_mut(), self.desc.entity, phase);
117+
self.kind_set = true;
137118
}
138119
};
139120
self
@@ -249,6 +230,22 @@ where
249230
/// * C++ API: `node_builder::build`
250231
#[doc(alias = "node_builder::build")]
251232
fn build(&mut self) -> Self::BuiltType {
233+
#[cfg(feature = "flecs_pipeline")]
234+
if !self.kind_set {
235+
unsafe {
236+
sys::ecs_add_id(
237+
self.world().world_ptr_mut(),
238+
self.desc.entity,
239+
ecs_dependson(ECS_ON_UPDATE),
240+
);
241+
sys::ecs_add_id(
242+
self.world().world_ptr_mut(),
243+
self.desc.entity,
244+
ECS_ON_UPDATE,
245+
);
246+
}
247+
}
248+
252249
let system = System::new(self.world(), self.desc);
253250
for s in self.term_builder.str_ptrs_to_free.iter_mut() {
254251
unsafe { core::mem::ManuallyDrop::drop(s) };

flecs_ecs/tests/flecs/system_test.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,6 +1652,26 @@ fn system_custom_pipeline_w_kind() {
16521652
});
16531653
}
16541654

1655+
#[test]
1656+
fn system_kind_while_deferred() {
1657+
let world = World::new();
1658+
1659+
let sys = world.defer(|| {
1660+
world
1661+
.system::<()>()
1662+
.kind_id(flecs::pipeline::OnValidate::ID)
1663+
.run(|_| {})
1664+
});
1665+
1666+
world.progress();
1667+
1668+
let sys = sys.entity_view(&world);
1669+
assert!(sys.has_id(flecs::pipeline::OnValidate::ID));
1670+
assert!(sys.has_first::<flecs::DependsOn>(flecs::pipeline::OnValidate::ID));
1671+
assert!(!sys.has_id(flecs::pipeline::OnUpdate::ID));
1672+
assert!(!sys.has_first::<flecs::DependsOn>(flecs::pipeline::OnUpdate::ID));
1673+
}
1674+
16551675
#[test]
16561676
fn system_create_w_no_template_args() {
16571677
let world = World::new();

0 commit comments

Comments
 (0)