Fix unsoundness in tick_dioxus_ui

This commit is contained in:
JMS55 2023-12-07 12:57:34 -08:00
parent b5856e77f7
commit aa06f3805b
2 changed files with 19 additions and 23 deletions

View file

@ -1,8 +1,7 @@
use crate::bsn::Bsn; use crate::bsn::Bsn;
use bevy::{ use bevy::{
ecs::{entity::Entity, world::World}, ecs::{entity::Entity, system::Commands},
hierarchy::{BuildWorldChildren, DespawnRecursiveExt}, hierarchy::{BuildChildren, DespawnRecursiveExt},
text::Text,
ui::node_bundles::TextBundle, ui::node_bundles::TextBundle,
utils::HashMap, utils::HashMap,
}; };
@ -13,7 +12,7 @@ pub fn apply_mutations(
element_id_to_bevy_ui_entity: &mut HashMap<ElementId, Entity>, element_id_to_bevy_ui_entity: &mut HashMap<ElementId, Entity>,
templates: &mut HashMap<String, Bsn>, templates: &mut HashMap<String, Bsn>,
root_entity: Entity, root_entity: Entity,
world: &mut World, commands: &mut Commands,
) { ) {
for new_template in mutations.templates { for new_template in mutations.templates {
templates.insert(new_template.name.to_owned(), todo!()); templates.insert(new_template.name.to_owned(), todo!());
@ -26,17 +25,17 @@ pub fn apply_mutations(
for edit in mutations.edits { for edit in mutations.edits {
match edit { match edit {
Mutation::AppendChildren { id, m } => { Mutation::AppendChildren { id, m } => {
let mut parent = world.entity_mut(map[&id]); let mut parent = commands.entity(map[&id]);
for _ in 0..m { for _ in 0..m {
parent.add_child(stack.pop().unwrap()); parent.add_child(stack.pop().unwrap());
} }
} }
Mutation::AssignId { path, id } => todo!(), Mutation::AssignId { path, id } => todo!(),
Mutation::CreatePlaceholder { id } => { Mutation::CreatePlaceholder { id } => {
map.insert(id, world.spawn(()).id()); map.insert(id, commands.spawn(()).id());
} }
Mutation::CreateTextNode { value, id } => { Mutation::CreateTextNode { value, id } => {
map.insert(id, world.spawn(TextBundle::from(value)).id()); map.insert(id, commands.spawn(TextBundle::from(value)).id());
} }
Mutation::HydrateText { path, value, id } => todo!(), Mutation::HydrateText { path, value, id } => todo!(),
Mutation::LoadTemplate { name, index, id } => todo!(), Mutation::LoadTemplate { name, index, id } => todo!(),
@ -50,19 +49,12 @@ pub fn apply_mutations(
id, id,
ns, ns,
} => todo!(), } => todo!(),
Mutation::SetText { value, id } => { Mutation::SetText { value, id } => todo!(),
world
.entity_mut(map[&id])
.get_mut::<Text>()
.unwrap()
.sections[0]
.value = value.to_owned();
}
Mutation::NewEventListener { name, id } => todo!(), Mutation::NewEventListener { name, id } => todo!(),
Mutation::RemoveEventListener { name, id } => todo!(), Mutation::RemoveEventListener { name, id } => todo!(),
Mutation::Remove { id } => { Mutation::Remove { id } => {
world commands
.entity_mut(map.remove(&id).unwrap()) .entity(map.remove(&id).unwrap())
.despawn_recursive(); .despawn_recursive();
} }
Mutation::PushRoot { id } => stack.push(map[&id]), Mutation::PushRoot { id } => stack.push(map[&id]),

View file

@ -4,6 +4,7 @@ use crate::{
use bevy::{ use bevy::{
ecs::{ ecs::{
entity::Entity, entity::Entity,
system::{CommandQueue, Commands},
world::{Mut, World}, world::{Mut, World},
}, },
prelude::{Deref, DerefMut}, prelude::{Deref, DerefMut},
@ -12,10 +13,11 @@ use bevy::{
use dioxus_core::{Element, Scope, ScopeState, VirtualDom}; use dioxus_core::{Element, Scope, ScopeState, VirtualDom};
use std::{mem, sync::Arc}; use std::{mem, sync::Arc};
// TODO: This is not sound. Can't borrow the world while iterating over DioxusUiRoots.
pub fn tick_dioxus_ui(world: &mut World) { pub fn tick_dioxus_ui(world: &mut 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 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
@ -35,29 +37,31 @@ pub fn tick_dioxus_ui(world: &mut World) {
.base_scope() .base_scope()
.provide_context(EcsContext { world: world_ptr }); .provide_context(EcsContext { world: world_ptr });
// TODO: Handle events from winit
// virtual_dom.handle_event(todo!(), todo!(), todo!(), todo!());
if *needs_rebuild { if *needs_rebuild {
apply_mutations( apply_mutations(
virtual_dom.rebuild(), virtual_dom.rebuild(),
element_id_to_bevy_ui_entity, element_id_to_bevy_ui_entity,
templates, templates,
root_entity, root_entity,
unsafe { world_cell.world_mut() }, &mut commands,
); );
*needs_rebuild = false; *needs_rebuild = false;
} }
// TODO: Handle events from winit
// virtual_dom.handle_event(todo!(), todo!(), todo!(), todo!());
apply_mutations( apply_mutations(
virtual_dom.render_immediate(), virtual_dom.render_immediate(),
element_id_to_bevy_ui_entity, element_id_to_bevy_ui_entity,
templates, templates,
root_entity, root_entity,
unsafe { world_cell.world_mut() }, &mut commands,
); );
} }
command_queue.apply(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);
} }