Fix segfault

This commit is contained in:
JMS55 2023-12-16 20:19:41 -08:00
parent fe22cc8709
commit fa03c65f8a
3 changed files with 27 additions and 19 deletions

View file

@ -1,4 +1,4 @@
use crate::deferred_system::new_deferred_system; use crate::{deferred_system::new_deferred_system, UiContext};
use bevy::{ use bevy::{
ecs::{ ecs::{
component::ComponentId, component::ComponentId,
@ -13,7 +13,7 @@ use dioxus::{
hooks::use_on_destroy, hooks::use_on_destroy,
}; };
#[derive(Resource, Default)] #[derive(Default)]
pub(crate) struct EcsSubscriptions { pub(crate) struct EcsSubscriptions {
pub resources: Box<HashMap<ComponentId, HashSet<ScopeId>>>, pub resources: Box<HashMap<ComponentId, HashSet<ScopeId>>>,
pub world_and_queries: Box<HashSet<ScopeId>>, pub world_and_queries: Box<HashSet<ScopeId>>,
@ -40,7 +40,10 @@ pub fn use_world<'a>(cx: &'a ScopeState) -> &'a World {
let scope_id = cx.scope_id(); let scope_id = cx.scope_id();
let subscription_manager = *cx.use_hook(|| { let subscription_manager = *cx.use_hook(|| {
let subscription_manager = &mut world.resource_mut::<EcsSubscriptions>().world_and_queries; let subscription_manager = &mut world
.non_send_resource_mut::<UiContext>()
.subscriptions
.world_and_queries;
subscription_manager.insert(scope_id); subscription_manager.insert(scope_id);
Box::as_mut(subscription_manager) as *mut HashSet<ScopeId> Box::as_mut(subscription_manager) as *mut HashSet<ScopeId>
}); });
@ -57,7 +60,10 @@ pub fn use_resource<'a, T: Resource>(cx: &'a ScopeState) -> &'a T {
let resource_id = world.components().resource_id::<T>().unwrap(); let resource_id = world.components().resource_id::<T>().unwrap();
let scope_id = cx.scope_id(); let scope_id = cx.scope_id();
let subscription_manager = *cx.use_hook(|| { let subscription_manager = *cx.use_hook(|| {
let subscription_manager = &mut world.resource_mut::<EcsSubscriptions>().resources; let subscription_manager = &mut world
.non_send_resource_mut::<UiContext>()
.subscriptions
.resources;
subscription_manager subscription_manager
.entry(resource_id) .entry(resource_id)
.or_default() .or_default()
@ -92,7 +98,10 @@ where
let scope_id = cx.scope_id(); let scope_id = cx.scope_id();
let subscription_manager = *cx.use_hook(|| { let subscription_manager = *cx.use_hook(|| {
let subscription_manager = &mut world.resource_mut::<EcsSubscriptions>().world_and_queries; let subscription_manager = &mut world
.non_send_resource_mut::<UiContext>()
.subscriptions
.world_and_queries;
subscription_manager.insert(scope_id); subscription_manager.insert(scope_id);
Box::as_mut(subscription_manager) as *mut HashSet<ScopeId> Box::as_mut(subscription_manager) as *mut HashSet<ScopeId>
}); });

View file

@ -12,7 +12,7 @@ use self::{
use bevy::{ use bevy::{
app::{App, Plugin, Update}, app::{App, Plugin, Update},
ecs::{bundle::Bundle, component::Component, entity::Entity}, ecs::{bundle::Bundle, component::Component, entity::Entity},
prelude::{Deref, DerefMut}, prelude::Deref,
ui::node_bundles::NodeBundle, ui::node_bundles::NodeBundle,
utils::{EntityHashMap, HashMap}, utils::{EntityHashMap, HashMap},
}; };
@ -25,9 +25,7 @@ pub struct DioxusUiPlugin;
impl Plugin for DioxusUiPlugin { impl Plugin for DioxusUiPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
// TODO: I think UiRoots must be dropped only after EcsSubscriptions app.init_non_send_resource::<UiContext>()
app.init_non_send_resource::<UiRoots>()
.init_resource::<EcsSubscriptions>()
.init_resource::<DeferredSystemRegistry>() .init_resource::<DeferredSystemRegistry>()
.init_resource::<EventReaders>() .init_resource::<EventReaders>()
.add_systems(Update, tick_dioxus_ui); .add_systems(Update, tick_dioxus_ui);
@ -43,8 +41,11 @@ pub struct DioxusUiBundle {
#[derive(Component, Deref, Hash, PartialEq, Eq, Clone, Copy)] #[derive(Component, Deref, Hash, PartialEq, Eq, Clone, Copy)]
pub struct DioxusUiRoot(pub fn(Scope) -> Element); pub struct DioxusUiRoot(pub fn(Scope) -> Element);
#[derive(Deref, DerefMut, Default)] #[derive(Default)]
struct UiRoots(HashMap<(Entity, DioxusUiRoot), UiRoot>); struct UiContext {
roots: HashMap<(Entity, DioxusUiRoot), UiRoot>,
subscriptions: EcsSubscriptions,
}
struct UiRoot { struct UiRoot {
virtual_dom: VirtualDom, virtual_dom: VirtualDom,

View file

@ -1,9 +1,6 @@
use crate::{ use crate::{
apply_mutations::apply_mutations, apply_mutations::apply_mutations, deferred_system::DeferredSystemRegistry,
deferred_system::DeferredSystemRegistry, events::EventReaders, hooks::EcsContext, DioxusUiRoot, UiContext, UiRoot,
events::EventReaders,
hooks::{EcsContext, EcsSubscriptions},
DioxusUiRoot, UiRoot, UiRoots,
}; };
use bevy::{ use bevy::{
ecs::{ ecs::{
@ -28,7 +25,7 @@ pub fn tick_dioxus_ui(world: &mut World) {
.iter(world) .iter(world)
.map(|(entity, ui_root)| (entity, *ui_root)) .map(|(entity, ui_root)| (entity, *ui_root))
.collect(); .collect();
let mut ui_roots = mem::take(&mut world.non_send_resource_mut::<UiRoots>().0); let mut ui_roots = mem::take(&mut world.non_send_resource_mut::<UiContext>().roots);
for (root_entity, dioxus_ui_root) in root_entities { for (root_entity, dioxus_ui_root) in root_entities {
let mut ui_root = ui_roots let mut ui_root = ui_roots
@ -42,7 +39,8 @@ pub fn tick_dioxus_ui(world: &mut World) {
render_ui(root_entity, &mut ui_root, world); render_ui(root_entity, &mut ui_root, world);
world world
.non_send_resource_mut::<UiRoots>() .non_send_resource_mut::<UiContext>()
.roots
.insert((root_entity, dioxus_ui_root), ui_root); .insert((root_entity, dioxus_ui_root), ui_root);
} }
} }
@ -82,7 +80,7 @@ fn dispatch_ui_events(
} }
fn schedule_ui_renders_from_ecs_subscriptions(ui_root: &mut UiRoot, world: &World) { fn schedule_ui_renders_from_ecs_subscriptions(ui_root: &mut UiRoot, world: &World) {
let ecs_subscriptions = world.resource::<EcsSubscriptions>(); let ecs_subscriptions = &world.non_send_resource::<UiContext>().subscriptions;
for scope_id in &*ecs_subscriptions.world_and_queries { for scope_id in &*ecs_subscriptions.world_and_queries {
ui_root.virtual_dom.mark_dirty(*scope_id); ui_root.virtual_dom.mark_dirty(*scope_id);