New system scheduler hook
This commit is contained in:
parent
9776f179f9
commit
cb57dca6b9
|
@ -48,13 +48,7 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseStateSend<Option<Entity>>) -
|
|||
let mut entities = entities.into_iter().collect::<Vec<_>>();
|
||||
entities.sort_by_key(|(entity, _)| *entity);
|
||||
|
||||
let spawn_entity = use_system(cx, {
|
||||
let selected_entity = (*selected_entity).clone();
|
||||
move |world: &mut World| {
|
||||
let new_entity = world.spawn_empty();
|
||||
selected_entity.write(Some(new_entity.id()));
|
||||
}
|
||||
});
|
||||
let system_scheduler = use_system_scheduler(cx);
|
||||
|
||||
render! {
|
||||
node {
|
||||
|
@ -87,7 +81,13 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseStateSend<Option<Entity>>) -
|
|||
}
|
||||
Button {
|
||||
onclick: move |event: Event<PointerButton>| if *event.data == PointerButton::Primary {
|
||||
spawn_entity();
|
||||
system_scheduler.schedule({
|
||||
let selected_entity = (*selected_entity).clone();
|
||||
move |world: &mut World| {
|
||||
let new_entity = world.spawn_empty();
|
||||
selected_entity.write(Some(new_entity.id()));
|
||||
}
|
||||
});
|
||||
event.stop_propagation();
|
||||
},
|
||||
text { text: "Spawn Entity", text_size: "18" }
|
||||
|
|
|
@ -1,54 +1,36 @@
|
|||
use bevy::{
|
||||
ecs::{
|
||||
system::{IntoSystem, Resource, SystemId},
|
||||
world::World,
|
||||
},
|
||||
utils::HashMap,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use crate::ecs_hooks::EcsContext;
|
||||
use bevy::ecs::system::{IntoSystem, Resource, System};
|
||||
use dioxus::core::ScopeState;
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct DeferredSystemRegistry {
|
||||
// TODO: Replace ref_counts with Box<Vec<SystemId>> and insert SystemId into it on unmount
|
||||
pub ref_counts: HashMap<SystemId, Arc<()>>,
|
||||
pub run_queue: Box<Vec<SystemId>>,
|
||||
pub struct DeferredSystemRunQueue {
|
||||
pub run_queue: Box<Vec<Box<dyn System<In = (), Out = ()>>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct DeferredSystem {
|
||||
id: SystemId,
|
||||
run_queue: *mut Vec<SystemId>,
|
||||
pub struct DeferredSystemScheduler {
|
||||
run_queue: *mut Vec<Box<dyn System<In = (), Out = ()>>>,
|
||||
}
|
||||
|
||||
impl DeferredSystem {
|
||||
fn schedule(&self) {
|
||||
unsafe { &mut *self.run_queue }.push(self.id);
|
||||
impl DeferredSystemScheduler {
|
||||
pub fn schedule<S, M>(&self, system: S)
|
||||
where
|
||||
S: IntoSystem<(), (), M> + 'static,
|
||||
M: 'static,
|
||||
{
|
||||
unsafe { &mut *self.run_queue }.push(Box::new(S::into_system(system)));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for DeferredSystem {}
|
||||
unsafe impl Sync for DeferredSystem {}
|
||||
unsafe impl Send for DeferredSystemScheduler {}
|
||||
unsafe impl Sync for DeferredSystemScheduler {}
|
||||
|
||||
pub fn new_deferred_system<S, M>(
|
||||
system: S,
|
||||
world: &mut World,
|
||||
) -> (impl Fn() + Send + Sync + Copy, Arc<()>)
|
||||
where
|
||||
S: IntoSystem<(), (), M> + 'static,
|
||||
M: 'static,
|
||||
{
|
||||
let id = world.register_system(system);
|
||||
let ref_count = Arc::new(());
|
||||
|
||||
let mut system_registry = world.resource_mut::<DeferredSystemRegistry>();
|
||||
system_registry
|
||||
.ref_counts
|
||||
.insert(id, Arc::clone(&ref_count));
|
||||
|
||||
let deferred_system = DeferredSystem {
|
||||
id,
|
||||
run_queue: Box::as_mut(&mut system_registry.run_queue),
|
||||
};
|
||||
|
||||
(move || deferred_system.schedule(), ref_count)
|
||||
pub fn use_system_scheduler(cx: &ScopeState) -> DeferredSystemScheduler {
|
||||
DeferredSystemScheduler {
|
||||
run_queue: Box::as_mut(
|
||||
&mut EcsContext::get_world(cx)
|
||||
.resource_mut::<DeferredSystemRunQueue>()
|
||||
.run_queue,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{deferred_system::new_deferred_system, UiContext};
|
||||
use crate::UiContext;
|
||||
use bevy::{
|
||||
ecs::{
|
||||
component::ComponentId,
|
||||
query::{QueryState, ReadOnlyWorldQuery},
|
||||
system::{IntoSystem, Query, Resource},
|
||||
system::{Query, Resource},
|
||||
world::{unsafe_world_cell::UnsafeWorldCell, World},
|
||||
},
|
||||
utils::{HashMap, HashSet},
|
||||
|
@ -13,6 +13,8 @@ use dioxus::{
|
|||
hooks::use_on_destroy,
|
||||
};
|
||||
|
||||
pub use crate::deferred_system::use_system_scheduler;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct EcsSubscriptions {
|
||||
pub resources: Box<HashMap<ComponentId, HashSet<ScopeId>>>,
|
||||
|
@ -25,7 +27,7 @@ pub(crate) struct EcsContext {
|
|||
}
|
||||
|
||||
impl EcsContext {
|
||||
fn get_world(cx: &ScopeState) -> &mut World {
|
||||
pub fn get_world(cx: &ScopeState) -> &mut World {
|
||||
unsafe {
|
||||
&mut *cx
|
||||
.consume_context::<EcsContext>()
|
||||
|
@ -115,15 +117,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn use_system<S, M>(cx: &ScopeState, system: S) -> impl Fn() + Send + Sync + Copy
|
||||
where
|
||||
S: IntoSystem<(), (), M> + 'static,
|
||||
M: 'static,
|
||||
{
|
||||
cx.use_hook(|| new_deferred_system(system, EcsContext::get_world(cx)))
|
||||
.0
|
||||
}
|
||||
|
||||
pub struct DioxusUiQuery<'a, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery> {
|
||||
query_state: QueryState<Q, F>,
|
||||
world_cell: UnsafeWorldCell<'a>,
|
||||
|
|
|
@ -13,7 +13,7 @@ mod use_state_send;
|
|||
|
||||
use self::{
|
||||
apply_mutations::BevyTemplate,
|
||||
deferred_system::DeferredSystemRegistry,
|
||||
deferred_system::DeferredSystemRunQueue,
|
||||
ecs_hooks::EcsSubscriptions,
|
||||
events::{generate_mouse_enter_leave_events, EventReaders, MouseEnter, MouseExit},
|
||||
tick::tick_dioxus_ui,
|
||||
|
@ -47,7 +47,7 @@ impl Plugin for DioxusUiPlugin {
|
|||
>::default());
|
||||
|
||||
app.init_non_send_resource::<UiContext>()
|
||||
.init_resource::<DeferredSystemRegistry>()
|
||||
.init_resource::<DeferredSystemRunQueue>()
|
||||
.init_resource::<EventReaders>()
|
||||
.add_event::<MouseEnter>()
|
||||
.add_event::<MouseExit>()
|
||||
|
|
19
src/tick.rs
19
src/tick.rs
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
apply_mutations::apply_mutations,
|
||||
deferred_system::DeferredSystemRegistry,
|
||||
deferred_system::DeferredSystemRunQueue,
|
||||
ecs_hooks::EcsContext,
|
||||
events::{bubble_event, EventReaders},
|
||||
DioxusUiRoot, UiContext, UiRoot,
|
||||
|
@ -12,7 +12,7 @@ use bevy::{
|
|||
},
|
||||
utils::HashMap,
|
||||
};
|
||||
use std::{any::Any, mem, rc::Rc, sync::Arc};
|
||||
use std::{any::Any, mem, rc::Rc};
|
||||
|
||||
pub fn tick_dioxus_ui(world: &mut World) {
|
||||
run_deferred_systems(world);
|
||||
|
@ -55,19 +55,10 @@ pub fn tick_dioxus_ui(world: &mut World) {
|
|||
}
|
||||
|
||||
fn run_deferred_systems(world: &mut World) {
|
||||
for system_id in mem::take(&mut *world.resource_mut::<DeferredSystemRegistry>().run_queue) {
|
||||
let _ = world.run_system(system_id);
|
||||
for mut system in mem::take(&mut *world.resource_mut::<DeferredSystemRunQueue>().run_queue) {
|
||||
system.initialize(world);
|
||||
let _ = system.run((), world);
|
||||
}
|
||||
|
||||
world.resource_scope(|world, mut system_registry: Mut<DeferredSystemRegistry>| {
|
||||
system_registry.ref_counts.retain(|system_id, ref_count| {
|
||||
let cleanup = Arc::strong_count(ref_count) == 1;
|
||||
if cleanup {
|
||||
world.remove_system(*system_id).unwrap();
|
||||
}
|
||||
!cleanup
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn dispatch_ui_events(
|
||||
|
|
Loading…
Reference in a new issue