WIP: Direct world access for tick_dioxus_ui()
This commit is contained in:
parent
98a22580a1
commit
138a2b5b20
|
@ -43,8 +43,6 @@ pub struct DioxusUiBundle {
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct DioxusUiRoot {
|
pub struct DioxusUiRoot {
|
||||||
virtual_dom: VirtualDomUnsafe,
|
virtual_dom: VirtualDomUnsafe,
|
||||||
parent_to_children: HashMap<(Entity, u8), Entity>,
|
|
||||||
children_to_parent: EntityHashMap<Entity, Entity>,
|
|
||||||
element_id_to_bevy_ui_entity: HashMap<ElementId, Entity>,
|
element_id_to_bevy_ui_entity: HashMap<ElementId, Entity>,
|
||||||
bevy_ui_entity_to_element_id: EntityHashMap<Entity, ElementId>,
|
bevy_ui_entity_to_element_id: EntityHashMap<Entity, ElementId>,
|
||||||
templates: HashMap<String, BevyTemplate>,
|
templates: HashMap<String, BevyTemplate>,
|
||||||
|
@ -55,8 +53,6 @@ impl DioxusUiRoot {
|
||||||
pub fn new(root_component: fn(Scope) -> Element) -> Self {
|
pub fn new(root_component: fn(Scope) -> Element) -> Self {
|
||||||
Self {
|
Self {
|
||||||
virtual_dom: VirtualDomUnsafe::new(root_component),
|
virtual_dom: VirtualDomUnsafe::new(root_component),
|
||||||
parent_to_children: HashMap::new(),
|
|
||||||
children_to_parent: EntityHashMap::default(),
|
|
||||||
element_id_to_bevy_ui_entity: HashMap::new(),
|
element_id_to_bevy_ui_entity: HashMap::new(),
|
||||||
bevy_ui_entity_to_element_id: EntityHashMap::default(),
|
bevy_ui_entity_to_element_id: EntityHashMap::default(),
|
||||||
templates: HashMap::new(),
|
templates: HashMap::new(),
|
||||||
|
|
152
src/tick.rs
152
src/tick.rs
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apply_mutations::apply_mutations,
|
apply_mutations::{apply_mutations, BevyTemplate},
|
||||||
deferred_system::DeferredSystemRegistry,
|
deferred_system::DeferredSystemRegistry,
|
||||||
events::EventReaders,
|
events::EventReaders,
|
||||||
hooks::{EcsContext, EcsSubscriptions},
|
hooks::{EcsContext, EcsSubscriptions},
|
||||||
|
@ -8,27 +8,27 @@ use crate::{
|
||||||
use bevy::{
|
use bevy::{
|
||||||
ecs::{
|
ecs::{
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
system::{CommandQueue, Commands},
|
|
||||||
world::{Mut, World},
|
world::{Mut, World},
|
||||||
},
|
},
|
||||||
|
hierarchy::Parent,
|
||||||
prelude::{Deref, DerefMut},
|
prelude::{Deref, DerefMut},
|
||||||
utils::synccell::SyncCell,
|
utils::{hashbrown::HashMap, synccell::SyncCell, EntityHashMap},
|
||||||
};
|
};
|
||||||
use dioxus::core::{Element, Scope, VirtualDom};
|
use dioxus::core::{Element, ElementId, Scope, VirtualDom};
|
||||||
use std::{mem, rc::Rc, sync::Arc};
|
use std::{any::Any, mem, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
pub fn tick_dioxus_ui(world: &mut World) {
|
pub fn tick_dioxus_ui(world: &mut World) {
|
||||||
|
run_deferred_systems(world);
|
||||||
|
|
||||||
let world_ptr: *mut World = world;
|
let world_ptr: *mut World = world;
|
||||||
let world_cell = world.as_unsafe_world_cell();
|
let world_cell = world.as_unsafe_world_cell();
|
||||||
let ecs_subscriptions = unsafe { world_cell.get_resource::<EcsSubscriptions>().unwrap() };
|
|
||||||
let events = unsafe {
|
let ui_events = unsafe {
|
||||||
world_cell
|
world_cell
|
||||||
.get_resource_mut::<EventReaders>()
|
.get_resource_mut::<EventReaders>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_dioxus_events(world_cell.get_resource().unwrap())
|
.get_dioxus_events(world_cell.get_resource().unwrap())
|
||||||
};
|
};
|
||||||
let mut command_queue = CommandQueue::default();
|
|
||||||
let mut commands = Commands::new_from_entities(&mut command_queue, world_cell.entities());
|
|
||||||
|
|
||||||
for (root_entity, mut dioxus_ui_root) in unsafe {
|
for (root_entity, mut dioxus_ui_root) in unsafe {
|
||||||
world_cell
|
world_cell
|
||||||
|
@ -38,8 +38,6 @@ pub fn tick_dioxus_ui(world: &mut World) {
|
||||||
} {
|
} {
|
||||||
let DioxusUiRoot {
|
let DioxusUiRoot {
|
||||||
virtual_dom,
|
virtual_dom,
|
||||||
parent_to_children,
|
|
||||||
children_to_parent,
|
|
||||||
element_id_to_bevy_ui_entity,
|
element_id_to_bevy_ui_entity,
|
||||||
bevy_ui_entity_to_element_id,
|
bevy_ui_entity_to_element_id,
|
||||||
templates,
|
templates,
|
||||||
|
@ -47,59 +45,33 @@ pub fn tick_dioxus_ui(world: &mut World) {
|
||||||
} = &mut *dioxus_ui_root;
|
} = &mut *dioxus_ui_root;
|
||||||
let virtual_dom = virtual_dom.get();
|
let virtual_dom = virtual_dom.get();
|
||||||
|
|
||||||
let schedule_update = virtual_dom.base_scope().schedule_update_any();
|
dispatch_ui_events(
|
||||||
for scope_id in &*ecs_subscriptions.world_and_queries {
|
&ui_events,
|
||||||
schedule_update(*scope_id);
|
bevy_ui_entity_to_element_id,
|
||||||
}
|
virtual_dom,
|
||||||
for (resource_id, scope_ids) in &*ecs_subscriptions.resources {
|
unsafe { world_cell.world() },
|
||||||
if unsafe { world_cell.world() }.is_resource_changed_by_id(*resource_id) {
|
);
|
||||||
for scope_id in scope_ids {
|
|
||||||
schedule_update(*scope_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual_dom
|
schedule_ui_renders_from_ecs_subscriptions(
|
||||||
.base_scope()
|
virtual_dom,
|
||||||
.provide_context(EcsContext { world: world_ptr });
|
unsafe { world_cell.get_resource::<EcsSubscriptions>().unwrap() },
|
||||||
|
unsafe { world_cell.world() },
|
||||||
|
);
|
||||||
|
|
||||||
for (mut target, name, data) in &events {
|
render_ui(
|
||||||
let mut target_element_id = bevy_ui_entity_to_element_id.get(&target);
|
virtual_dom,
|
||||||
while target_element_id.is_none() {
|
needs_rebuild,
|
||||||
target = children_to_parent[&target];
|
|
||||||
target_element_id = bevy_ui_entity_to_element_id.get(&target);
|
|
||||||
}
|
|
||||||
virtual_dom.handle_event(name, Rc::clone(data), *target_element_id.unwrap(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if *needs_rebuild {
|
|
||||||
apply_mutations(
|
|
||||||
virtual_dom.rebuild(),
|
|
||||||
parent_to_children,
|
|
||||||
children_to_parent,
|
|
||||||
element_id_to_bevy_ui_entity,
|
|
||||||
bevy_ui_entity_to_element_id,
|
|
||||||
templates,
|
|
||||||
root_entity,
|
|
||||||
&mut commands,
|
|
||||||
);
|
|
||||||
*needs_rebuild = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_mutations(
|
|
||||||
virtual_dom.render_immediate(),
|
|
||||||
parent_to_children,
|
|
||||||
children_to_parent,
|
|
||||||
element_id_to_bevy_ui_entity,
|
element_id_to_bevy_ui_entity,
|
||||||
bevy_ui_entity_to_element_id,
|
bevy_ui_entity_to_element_id,
|
||||||
templates,
|
templates,
|
||||||
root_entity,
|
root_entity,
|
||||||
&mut commands,
|
unsafe { world_cell.world_mut() },
|
||||||
|
world_ptr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
command_queue.apply(world);
|
fn run_deferred_systems(world: &mut World) {
|
||||||
|
|
||||||
for system_id in mem::take(&mut *world.resource_mut::<DeferredSystemRegistry>().run_queue) {
|
for system_id in mem::take(&mut *world.resource_mut::<DeferredSystemRegistry>().run_queue) {
|
||||||
let _ = world.run_system(system_id);
|
let _ = world.run_system(system_id);
|
||||||
}
|
}
|
||||||
|
@ -115,6 +87,76 @@ pub fn tick_dioxus_ui(world: &mut World) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn schedule_ui_renders_from_ecs_subscriptions(
|
||||||
|
virtual_dom: &mut VirtualDom,
|
||||||
|
ecs_subscriptions: &EcsSubscriptions,
|
||||||
|
world: &World,
|
||||||
|
) {
|
||||||
|
let schedule_update = virtual_dom.base_scope().schedule_update_any();
|
||||||
|
for scope_id in &*ecs_subscriptions.world_and_queries {
|
||||||
|
schedule_update(*scope_id);
|
||||||
|
}
|
||||||
|
for (resource_id, scope_ids) in &*ecs_subscriptions.resources {
|
||||||
|
if world.is_resource_changed_by_id(*resource_id) {
|
||||||
|
for scope_id in scope_ids {
|
||||||
|
schedule_update(*scope_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_ui_events(
|
||||||
|
events: &Vec<(Entity, &str, Rc<dyn Any>)>,
|
||||||
|
bevy_ui_entity_to_element_id: &mut EntityHashMap<Entity, ElementId>,
|
||||||
|
virtual_dom: &mut VirtualDom,
|
||||||
|
world: &World,
|
||||||
|
) {
|
||||||
|
for (mut target, name, data) in events {
|
||||||
|
let mut target_element_id = bevy_ui_entity_to_element_id.get(&target);
|
||||||
|
while target_element_id.is_none() {
|
||||||
|
target = world.entity(target).get::<Parent>().unwrap().get();
|
||||||
|
target_element_id = bevy_ui_entity_to_element_id.get(&target);
|
||||||
|
}
|
||||||
|
virtual_dom.handle_event(name, Rc::clone(data), *target_element_id.unwrap(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ui(
|
||||||
|
virtual_dom: &mut VirtualDom,
|
||||||
|
needs_rebuild: &mut bool,
|
||||||
|
element_id_to_bevy_ui_entity: &mut HashMap<ElementId, Entity>,
|
||||||
|
bevy_ui_entity_to_element_id: &mut EntityHashMap<Entity, ElementId>,
|
||||||
|
templates: &mut HashMap<String, BevyTemplate>,
|
||||||
|
root_entity: Entity,
|
||||||
|
world: &mut World,
|
||||||
|
world_ptr: *mut World,
|
||||||
|
) {
|
||||||
|
virtual_dom
|
||||||
|
.base_scope()
|
||||||
|
.provide_context(EcsContext { world: world_ptr });
|
||||||
|
|
||||||
|
if *needs_rebuild {
|
||||||
|
apply_mutations(
|
||||||
|
virtual_dom.rebuild(),
|
||||||
|
element_id_to_bevy_ui_entity,
|
||||||
|
bevy_ui_entity_to_element_id,
|
||||||
|
templates,
|
||||||
|
root_entity,
|
||||||
|
world,
|
||||||
|
);
|
||||||
|
*needs_rebuild = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_mutations(
|
||||||
|
virtual_dom.render_immediate(),
|
||||||
|
element_id_to_bevy_ui_entity,
|
||||||
|
bevy_ui_entity_to_element_id,
|
||||||
|
templates,
|
||||||
|
root_entity,
|
||||||
|
world,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deref, DerefMut)]
|
#[derive(Deref, DerefMut)]
|
||||||
pub struct VirtualDomUnsafe(pub SyncCell<VirtualDom>);
|
pub struct VirtualDomUnsafe(pub SyncCell<VirtualDom>);
|
||||||
unsafe impl Send for VirtualDomUnsafe {}
|
unsafe impl Send for VirtualDomUnsafe {}
|
||||||
|
|
Loading…
Reference in a new issue