From cb57dca6b9f338d6356ec92b0cc62539a0387be9 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Wed, 27 Dec 2023 11:19:02 -0800 Subject: [PATCH] New system scheduler hook --- examples/demo.rs | 16 +++++----- src/deferred_system.rs | 66 +++++++++++++++--------------------------- src/ecs_hooks.rs | 17 ++++------- src/lib.rs | 4 +-- src/tick.rs | 19 ++++-------- 5 files changed, 44 insertions(+), 78 deletions(-) diff --git a/examples/demo.rs b/examples/demo.rs index 878608c..9155fda 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -48,13 +48,7 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseStateSend>) - let mut entities = entities.into_iter().collect::>(); 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>) - } Button { onclick: move |event: Event| 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" } diff --git a/src/deferred_system.rs b/src/deferred_system.rs index 9ed6ae7..76fee74 100644 --- a/src/deferred_system.rs +++ b/src/deferred_system.rs @@ -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> and insert SystemId into it on unmount - pub ref_counts: HashMap>, - pub run_queue: Box>, +pub struct DeferredSystemRunQueue { + pub run_queue: Box>>>, } #[derive(Clone, Copy)] -struct DeferredSystem { - id: SystemId, - run_queue: *mut Vec, +pub struct DeferredSystemScheduler { + run_queue: *mut Vec>>, } -impl DeferredSystem { - fn schedule(&self) { - unsafe { &mut *self.run_queue }.push(self.id); +impl DeferredSystemScheduler { + pub fn schedule(&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( - 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::(); - 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::() + .run_queue, + ), + } } diff --git a/src/ecs_hooks.rs b/src/ecs_hooks.rs index 161dbba..3c061aa 100644 --- a/src/ecs_hooks.rs +++ b/src/ecs_hooks.rs @@ -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>>, @@ -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::() @@ -115,15 +117,6 @@ where } } -pub fn use_system(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, world_cell: UnsafeWorldCell<'a>, diff --git a/src/lib.rs b/src/lib.rs index bd56a6d..0a370e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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::() - .init_resource::() + .init_resource::() .init_resource::() .add_event::() .add_event::() diff --git a/src/tick.rs b/src/tick.rs index d971608..3835107 100644 --- a/src/tick.rs +++ b/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::().run_queue) { - let _ = world.run_system(system_id); + for mut system in mem::take(&mut *world.resource_mut::().run_queue) { + system.initialize(world); + let _ = system.run((), world); } - - world.resource_scope(|world, mut system_registry: Mut| { - 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(