2023-12-07 02:46:50 +00:00
|
|
|
use crate::{
|
2023-12-16 00:53:25 +00:00
|
|
|
apply_mutations::apply_mutations,
|
2023-12-15 20:36:53 +00:00
|
|
|
deferred_system::DeferredSystemRegistry,
|
|
|
|
|
events::EventReaders,
|
|
|
|
|
hooks::{EcsContext, EcsSubscriptions},
|
|
|
|
|
DioxusUiRoot,
|
2023-12-07 02:46:50 +00:00
|
|
|
};
|
|
|
|
|
use bevy::{
|
2023-12-07 20:25:02 +00:00
|
|
|
ecs::{
|
|
|
|
|
entity::Entity,
|
2023-12-16 00:53:25 +00:00
|
|
|
query::With,
|
2023-12-16 01:04:29 +00:00
|
|
|
world::{Mut, World},
|
2023-12-07 20:25:02 +00:00
|
|
|
},
|
2023-12-16 00:20:05 +00:00
|
|
|
hierarchy::Parent,
|
2023-12-07 02:46:50 +00:00
|
|
|
prelude::{Deref, DerefMut},
|
2023-12-16 00:53:25 +00:00
|
|
|
utils::synccell::SyncCell,
|
2023-12-07 02:46:50 +00:00
|
|
|
};
|
2023-12-16 00:53:25 +00:00
|
|
|
use dioxus::core::{Element, Scope, VirtualDom};
|
2023-12-16 00:20:05 +00:00
|
|
|
use std::{any::Any, mem, rc::Rc, sync::Arc};
|
2023-12-07 02:46:50 +00:00
|
|
|
|
|
|
|
|
pub fn tick_dioxus_ui(world: &mut World) {
|
2023-12-16 00:20:05 +00:00
|
|
|
run_deferred_systems(world);
|
|
|
|
|
|
2023-12-16 00:53:25 +00:00
|
|
|
let ui_events = world.resource_scope(|world, mut event_readers: Mut<EventReaders>| {
|
|
|
|
|
event_readers.get_dioxus_events(world.resource())
|
|
|
|
|
});
|
|
|
|
|
let root_entities: Vec<Entity> = world
|
|
|
|
|
.query_filtered::<Entity, With<DioxusUiRoot>>()
|
|
|
|
|
.iter(world)
|
|
|
|
|
.collect();
|
2023-12-07 02:46:50 +00:00
|
|
|
|
2023-12-16 00:53:25 +00:00
|
|
|
for root_entity in root_entities {
|
2023-12-16 01:04:29 +00:00
|
|
|
dispatch_ui_events(&ui_events, root_entity, world);
|
2023-12-07 20:57:34 +00:00
|
|
|
|
2023-12-16 00:53:25 +00:00
|
|
|
schedule_ui_renders_from_ecs_subscriptions(root_entity, world);
|
2023-12-07 02:46:50 +00:00
|
|
|
|
2023-12-16 00:53:25 +00:00
|
|
|
render_ui(root_entity, world);
|
2023-12-07 02:46:50 +00:00
|
|
|
}
|
2023-12-16 00:20:05 +00:00
|
|
|
}
|
2023-12-07 02:46:50 +00:00
|
|
|
|
2023-12-16 00:20:05 +00:00
|
|
|
fn run_deferred_systems(world: &mut World) {
|
2023-12-07 20:25:02 +00:00
|
|
|
for system_id in mem::take(&mut *world.resource_mut::<DeferredSystemRegistry>().run_queue) {
|
|
|
|
|
let _ = world.run_system(system_id);
|
2023-12-07 02:46:50 +00:00
|
|
|
}
|
2023-12-07 20:25:02 +00:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
});
|
|
|
|
|
});
|
2023-12-07 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-16 00:53:25 +00:00
|
|
|
fn dispatch_ui_events(
|
|
|
|
|
events: &Vec<(Entity, &str, Rc<dyn Any>)>,
|
|
|
|
|
root_entity: Entity,
|
2023-12-16 01:04:29 +00:00
|
|
|
world: &mut World,
|
2023-12-16 00:20:05 +00:00
|
|
|
) {
|
2023-12-16 01:04:29 +00:00
|
|
|
let mut ui_root = world
|
|
|
|
|
.entity_mut(root_entity)
|
|
|
|
|
.take::<DioxusUiRoot>()
|
|
|
|
|
.unwrap();
|
2023-12-16 00:53:25 +00:00
|
|
|
|
|
|
|
|
for (mut target, name, data) in events {
|
|
|
|
|
let mut target_element_id = ui_root.bevy_ui_entity_to_element_id.get(&target).copied();
|
|
|
|
|
while target_element_id.is_none() {
|
2023-12-16 01:04:29 +00:00
|
|
|
target = world.entity(target).get::<Parent>().unwrap().get();
|
2023-12-16 00:53:25 +00:00
|
|
|
target_element_id = ui_root.bevy_ui_entity_to_element_id.get(&target).copied();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui_root.virtual_dom.get().handle_event(
|
|
|
|
|
name,
|
|
|
|
|
Rc::clone(data),
|
|
|
|
|
target_element_id.unwrap(),
|
|
|
|
|
true,
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-12-16 01:04:29 +00:00
|
|
|
|
|
|
|
|
world.entity_mut(root_entity).insert(ui_root);
|
2023-12-16 00:53:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn schedule_ui_renders_from_ecs_subscriptions(root_entity: Entity, world: &mut World) {
|
|
|
|
|
let schedule_update = world
|
|
|
|
|
.get_mut::<DioxusUiRoot>(root_entity)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.virtual_dom
|
|
|
|
|
.get()
|
|
|
|
|
.base_scope()
|
|
|
|
|
.schedule_update_any();
|
|
|
|
|
|
|
|
|
|
let ecs_subscriptions = world.resource::<EcsSubscriptions>();
|
|
|
|
|
|
2023-12-16 00:20:05 +00:00
|
|
|
for scope_id in &*ecs_subscriptions.world_and_queries {
|
|
|
|
|
schedule_update(*scope_id);
|
|
|
|
|
}
|
2023-12-16 00:53:25 +00:00
|
|
|
|
2023-12-16 00:20:05 +00:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-16 00:53:25 +00:00
|
|
|
fn render_ui(root_entity: Entity, world: &mut World) {
|
2023-12-16 01:04:29 +00:00
|
|
|
let mut ui_root = world
|
|
|
|
|
.entity_mut(root_entity)
|
|
|
|
|
.take::<DioxusUiRoot>()
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
ui_root
|
|
|
|
|
.virtual_dom
|
|
|
|
|
.get()
|
2023-12-16 00:20:05 +00:00
|
|
|
.base_scope()
|
2023-12-16 00:53:25 +00:00
|
|
|
.provide_context(EcsContext { world });
|
2023-12-16 00:20:05 +00:00
|
|
|
|
2023-12-16 01:04:29 +00:00
|
|
|
if ui_root.needs_rebuild {
|
2023-12-16 00:20:05 +00:00
|
|
|
apply_mutations(
|
2023-12-16 01:04:29 +00:00
|
|
|
ui_root.virtual_dom.get().rebuild(),
|
|
|
|
|
&mut ui_root.element_id_to_bevy_ui_entity,
|
|
|
|
|
&mut ui_root.bevy_ui_entity_to_element_id,
|
|
|
|
|
&mut ui_root.templates,
|
2023-12-16 00:20:05 +00:00
|
|
|
root_entity,
|
|
|
|
|
world,
|
|
|
|
|
);
|
2023-12-16 01:04:29 +00:00
|
|
|
ui_root.needs_rebuild = false;
|
2023-12-16 00:20:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
apply_mutations(
|
2023-12-16 01:04:29 +00:00
|
|
|
ui_root.virtual_dom.get().render_immediate(),
|
|
|
|
|
&mut ui_root.element_id_to_bevy_ui_entity,
|
|
|
|
|
&mut ui_root.bevy_ui_entity_to_element_id,
|
|
|
|
|
&mut ui_root.templates,
|
2023-12-16 00:20:05 +00:00
|
|
|
root_entity,
|
|
|
|
|
world,
|
|
|
|
|
);
|
2023-12-16 01:04:29 +00:00
|
|
|
|
|
|
|
|
world.entity_mut(root_entity).insert(ui_root);
|
2023-12-16 00:20:05 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-07 02:46:50 +00:00
|
|
|
#[derive(Deref, DerefMut)]
|
|
|
|
|
pub struct VirtualDomUnsafe(pub SyncCell<VirtualDom>);
|
|
|
|
|
unsafe impl Send for VirtualDomUnsafe {}
|
|
|
|
|
|
|
|
|
|
impl VirtualDomUnsafe {
|
|
|
|
|
pub fn new(root_component: fn(Scope) -> Element) -> Self {
|
|
|
|
|
Self(SyncCell::new(VirtualDom::new(root_component)))
|
|
|
|
|
}
|
|
|
|
|
}
|