diff --git a/src/apply_mutations.rs b/src/apply_mutations.rs index 872edf4..ac5f804 100644 --- a/src/apply_mutations.rs +++ b/src/apply_mutations.rs @@ -14,7 +14,8 @@ use dioxus::core::{ElementId, Mutation, Mutations, Template, TemplateAttribute, pub fn apply_mutations( mutations: Mutations, - hierarchy: &mut HashMap<(Entity, u8), Entity>, + parent_to_children: &mut HashMap<(Entity, u8), Entity>, + children_to_parent: &mut EntityHashMap, element_id_to_bevy_ui_entity: &mut HashMap, bevy_ui_entity_to_element_id: &mut EntityHashMap, templates: &mut HashMap, @@ -36,11 +37,13 @@ pub fn apply_mutations( match edit { Mutation::AppendChildren { id, m } => { let mut parent = commands.entity(element_id_to_bevy_ui_entity[&id]); - let parent_existing_child_count = - hierarchy.keys().filter(|(p, _)| *p == parent.id()).count(); + let parent_existing_child_count = parent_to_children + .keys() + .filter(|(p, _)| *p == parent.id()) + .count(); for (i, child) in stack.drain((stack.len() - m)..).enumerate() { parent.add_child(child); - hierarchy.insert( + parent_to_children.insert( (parent.id(), (parent_existing_child_count + i + 1) as u8), child, ); @@ -50,7 +53,7 @@ pub fn apply_mutations( Mutation::CreatePlaceholder { id } => todo!(), Mutation::CreateTextNode { value, id } => { let entity = BevyTemplateNode::from_dioxus(&TemplateNode::Text { text: value }) - .spawn(commands, hierarchy); + .spawn(commands, parent_to_children, children_to_parent); element_id_to_bevy_ui_entity.insert(id, entity); bevy_ui_entity_to_element_id.insert(entity, id); stack.push(entity); @@ -58,7 +61,7 @@ pub fn apply_mutations( Mutation::HydrateText { path, value, id } => { let mut entity = *stack.last().unwrap(); for index in path { - entity = hierarchy[&(entity, *index)]; + entity = parent_to_children[&(entity, *index)]; } commands .entity(entity) @@ -67,7 +70,11 @@ pub fn apply_mutations( bevy_ui_entity_to_element_id.insert(entity, id); } Mutation::LoadTemplate { name, index, id } => { - let entity = templates[name].roots[index].spawn(commands, hierarchy); + let entity = templates[name].roots[index].spawn( + commands, + parent_to_children, + children_to_parent, + ); element_id_to_bevy_ui_entity.insert(id, entity); bevy_ui_entity_to_element_id.insert(entity, id); stack.push(entity); @@ -155,14 +162,15 @@ impl BevyTemplateNode { fn spawn( &self, commands: &mut Commands, - hierarchy: &mut HashMap<(Entity, u8), Entity>, + parent_to_children: &mut HashMap<(Entity, u8), Entity>, + children_to_parent: &mut EntityHashMap, ) -> Entity { match self { BevyTemplateNode::Node { style, children } => { // TODO: Can probably use with_children() instead let children = children .iter() - .map(|child| child.spawn(commands, hierarchy)) + .map(|child| child.spawn(commands, parent_to_children, children_to_parent)) .collect::>(); let parent = commands .spawn(NodeBundle { @@ -172,7 +180,8 @@ impl BevyTemplateNode { .push_children(&children) .id(); for (i, child) in children.iter().enumerate() { - hierarchy.insert((parent, i as u8), *child); + parent_to_children.insert((parent, i as u8), *child); + children_to_parent.insert(*child, parent); } parent } diff --git a/src/lib.rs b/src/lib.rs index 55ca3fe..1c953e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,8 @@ pub struct DioxusUiBundle { #[derive(Component)] pub struct DioxusUiRoot { virtual_dom: VirtualDomUnsafe, - hierarchy: HashMap<(Entity, u8), Entity>, + parent_to_children: HashMap<(Entity, u8), Entity>, + children_to_parent: EntityHashMap, element_id_to_bevy_ui_entity: HashMap, bevy_ui_entity_to_element_id: EntityHashMap, templates: HashMap, @@ -54,7 +55,8 @@ impl DioxusUiRoot { pub fn new(root_component: fn(Scope) -> Element) -> Self { Self { virtual_dom: VirtualDomUnsafe::new(root_component), - hierarchy: HashMap::new(), + parent_to_children: HashMap::new(), + children_to_parent: EntityHashMap::default(), element_id_to_bevy_ui_entity: HashMap::new(), bevy_ui_entity_to_element_id: EntityHashMap::default(), templates: HashMap::new(), diff --git a/src/tick.rs b/src/tick.rs index c06646b..d26953e 100644 --- a/src/tick.rs +++ b/src/tick.rs @@ -35,7 +35,8 @@ pub fn tick_dioxus_ui(world: &mut World) { } { let DioxusUiRoot { virtual_dom, - hierarchy, + parent_to_children, + children_to_parent, element_id_to_bevy_ui_entity, bevy_ui_entity_to_element_id, templates, @@ -59,16 +60,20 @@ pub fn tick_dioxus_ui(world: &mut World) { .base_scope() .provide_context(EcsContext { world: world_ptr }); - for (target, name, data) in &events { - if let Some(target) = bevy_ui_entity_to_element_id.get(target) { - virtual_dom.handle_event(name, Rc::clone(data), *target, true); + 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 = 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(), - hierarchy, + parent_to_children, + children_to_parent, element_id_to_bevy_ui_entity, bevy_ui_entity_to_element_id, templates, @@ -80,7 +85,8 @@ pub fn tick_dioxus_ui(world: &mut World) { apply_mutations( virtual_dom.render_immediate(), - hierarchy, + parent_to_children, + children_to_parent, element_id_to_bevy_ui_entity, bevy_ui_entity_to_element_id, templates,