Fix event handlers not finding target element

This commit is contained in:
JMS55 2023-12-12 17:31:47 -08:00
parent 54f7e5c022
commit 035311036d
3 changed files with 35 additions and 18 deletions

View file

@ -14,7 +14,8 @@ use dioxus::core::{ElementId, Mutation, Mutations, Template, TemplateAttribute,
pub fn apply_mutations( pub fn apply_mutations(
mutations: Mutations, mutations: Mutations,
hierarchy: &mut HashMap<(Entity, u8), Entity>, parent_to_children: &mut HashMap<(Entity, u8), Entity>,
children_to_parent: &mut EntityHashMap<Entity, Entity>,
element_id_to_bevy_ui_entity: &mut HashMap<ElementId, Entity>, element_id_to_bevy_ui_entity: &mut HashMap<ElementId, Entity>,
bevy_ui_entity_to_element_id: &mut EntityHashMap<Entity, ElementId>, bevy_ui_entity_to_element_id: &mut EntityHashMap<Entity, ElementId>,
templates: &mut HashMap<String, BevyTemplate>, templates: &mut HashMap<String, BevyTemplate>,
@ -36,11 +37,13 @@ pub fn apply_mutations(
match edit { match edit {
Mutation::AppendChildren { id, m } => { Mutation::AppendChildren { id, m } => {
let mut parent = commands.entity(element_id_to_bevy_ui_entity[&id]); let mut parent = commands.entity(element_id_to_bevy_ui_entity[&id]);
let parent_existing_child_count = let parent_existing_child_count = parent_to_children
hierarchy.keys().filter(|(p, _)| *p == parent.id()).count(); .keys()
.filter(|(p, _)| *p == parent.id())
.count();
for (i, child) in stack.drain((stack.len() - m)..).enumerate() { for (i, child) in stack.drain((stack.len() - m)..).enumerate() {
parent.add_child(child); parent.add_child(child);
hierarchy.insert( parent_to_children.insert(
(parent.id(), (parent_existing_child_count + i + 1) as u8), (parent.id(), (parent_existing_child_count + i + 1) as u8),
child, child,
); );
@ -50,7 +53,7 @@ pub fn apply_mutations(
Mutation::CreatePlaceholder { id } => todo!(), Mutation::CreatePlaceholder { id } => todo!(),
Mutation::CreateTextNode { value, id } => { Mutation::CreateTextNode { value, id } => {
let entity = BevyTemplateNode::from_dioxus(&TemplateNode::Text { text: value }) 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); element_id_to_bevy_ui_entity.insert(id, entity);
bevy_ui_entity_to_element_id.insert(entity, id); bevy_ui_entity_to_element_id.insert(entity, id);
stack.push(entity); stack.push(entity);
@ -58,7 +61,7 @@ pub fn apply_mutations(
Mutation::HydrateText { path, value, id } => { Mutation::HydrateText { path, value, id } => {
let mut entity = *stack.last().unwrap(); let mut entity = *stack.last().unwrap();
for index in path { for index in path {
entity = hierarchy[&(entity, *index)]; entity = parent_to_children[&(entity, *index)];
} }
commands commands
.entity(entity) .entity(entity)
@ -67,7 +70,11 @@ pub fn apply_mutations(
bevy_ui_entity_to_element_id.insert(entity, id); bevy_ui_entity_to_element_id.insert(entity, id);
} }
Mutation::LoadTemplate { name, index, 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); element_id_to_bevy_ui_entity.insert(id, entity);
bevy_ui_entity_to_element_id.insert(entity, id); bevy_ui_entity_to_element_id.insert(entity, id);
stack.push(entity); stack.push(entity);
@ -155,14 +162,15 @@ impl BevyTemplateNode {
fn spawn( fn spawn(
&self, &self,
commands: &mut Commands, commands: &mut Commands,
hierarchy: &mut HashMap<(Entity, u8), Entity>, parent_to_children: &mut HashMap<(Entity, u8), Entity>,
children_to_parent: &mut EntityHashMap<Entity, Entity>,
) -> Entity { ) -> Entity {
match self { match self {
BevyTemplateNode::Node { style, children } => { BevyTemplateNode::Node { style, children } => {
// TODO: Can probably use with_children() instead // TODO: Can probably use with_children() instead
let children = children let children = children
.iter() .iter()
.map(|child| child.spawn(commands, hierarchy)) .map(|child| child.spawn(commands, parent_to_children, children_to_parent))
.collect::<Box<[_]>>(); .collect::<Box<[_]>>();
let parent = commands let parent = commands
.spawn(NodeBundle { .spawn(NodeBundle {
@ -172,7 +180,8 @@ impl BevyTemplateNode {
.push_children(&children) .push_children(&children)
.id(); .id();
for (i, child) in children.iter().enumerate() { 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 parent
} }

View file

@ -43,7 +43,8 @@ pub struct DioxusUiBundle {
#[derive(Component)] #[derive(Component)]
pub struct DioxusUiRoot { pub struct DioxusUiRoot {
virtual_dom: VirtualDomUnsafe, virtual_dom: VirtualDomUnsafe,
hierarchy: HashMap<(Entity, u8), Entity>, 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>,
@ -54,7 +55,8 @@ 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),
hierarchy: HashMap::new(), 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(),

View file

@ -35,7 +35,8 @@ pub fn tick_dioxus_ui(world: &mut World) {
} { } {
let DioxusUiRoot { let DioxusUiRoot {
virtual_dom, virtual_dom,
hierarchy, 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,
@ -59,16 +60,20 @@ pub fn tick_dioxus_ui(world: &mut World) {
.base_scope() .base_scope()
.provide_context(EcsContext { world: world_ptr }); .provide_context(EcsContext { world: world_ptr });
for (target, name, data) in &events { for (mut target, name, data) in &events {
if let Some(target) = bevy_ui_entity_to_element_id.get(target) { let mut target_element_id = bevy_ui_entity_to_element_id.get(&target);
virtual_dom.handle_event(name, Rc::clone(data), *target, true); 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 { if *needs_rebuild {
apply_mutations( apply_mutations(
virtual_dom.rebuild(), virtual_dom.rebuild(),
hierarchy, 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,
@ -80,7 +85,8 @@ pub fn tick_dioxus_ui(world: &mut World) {
apply_mutations( apply_mutations(
virtual_dom.render_immediate(), virtual_dom.render_immediate(),
hierarchy, 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,