From cdab72287a24ce46226236d3da6f34ff4328ca01 Mon Sep 17 00:00:00 2001
From: John Mitchell <6656977+StarArawn@users.noreply.github.com>
Date: Mon, 1 May 2023 20:24:13 -0400
Subject: [PATCH] Fixed issues with conditional widgets not working correctly.
 Fixed issues with cloned entities not being removed correctly.

---
 src/context.rs | 48 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 40 insertions(+), 8 deletions(-)

diff --git a/src/context.rs b/src/context.rs
index 6d6c870..d3df25c 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -731,12 +731,13 @@ fn update_widgets(
     unique_ids_parents: &Arc<RwLock<HashMap<Entity, Entity>>>,
 ) {
     for entity in widgets.iter() {
-        if let (Some(entity_ref), Some(_)) = (
-            world.get_entity(entity.0),
-            tree.try_write()
-                .ok()
-                .map(|tree| tree.contains(*entity).clone()),
-        ) {
+        // if let (Some(entity_ref), Some(_)) = (
+        //     world.get_entity(entity.0),
+        //     tree.try_write()
+        //         .ok()
+        //         .map(|tree| tree.contains(*entity).clone()),
+        // )
+        if let Some(entity_ref) = world.get_entity(entity.0) {
             if let Some(widget_type) = entity_ref.get::<WidgetName>() {
                 let widget_context = KayakWidgetContext::new(
                     tree.clone(),
@@ -796,6 +797,7 @@ fn update_widgets(
                         'outer: for (_index, changed_entity, parent, changes) in diff.changes.iter()
                         {
                             // If a tree node goes from A to B we need to know and delete the descendants.
+                            let mut remove_state = Vec::default();
                             if let Ok(previous_entities) = cloned_widget_entities.read() {
                                 if let Some(previous_entity) =
                                     previous_entities.get(&changed_entity.0)
@@ -809,6 +811,8 @@ fn update_widgets(
                                             prev_entity_ref.get::<WidgetName>(),
                                         ) {
                                             if widget_name != prev_widget_name {
+                                                // It doesn't matter we always need to remove state
+                                                remove_state.push(changed_entity.0);
                                                 if let Some(_) = tree.parent(*changed_entity) {
                                                     for child in
                                                         tree.down_iter_at(*changed_entity, false)
@@ -875,13 +879,32 @@ fn update_widgets(
                                 }
                             }
 
+                            for entity in remove_state.iter() { 
+                                if let Some(state_entity) = widget_state.remove(*entity) {
+                                    if let Some(mut entity_mut) = world.get_entity_mut(state_entity) {
+                                        entity_mut.remove_parent();
+                                        entity_mut.despawn_recursive();
+                                    }
+                                }
+                                // Also remove all cloned widget entities
+                                if let Ok(mut cloned_widget_entities) =
+                                    cloned_widget_entities.try_write()
+                                {
+                                    if let Some(target) = cloned_widget_entities.get(entity) {
+                                        world.despawn(*target);
+                                    }
+                                    cloned_widget_entities.remove(entity);
+                                }
+                            }
+
                             if changes.iter().any(|change| *change == Change::Inserted) {
                                 if let Some(mut entity_commands) =
                                     world.get_entity_mut(changed_entity.0)
                                 {
-                                    entity_commands.insert(Mounted);
                                     entity_commands.remove::<bevy::prelude::Parent>();
                                     entity_commands.set_parent(parent.0);
+                                    entity_commands.insert(Mounted);
+                                    entity_commands.insert(DirtyNode);
                                 }
                                 if world.get_entity(changed_entity.0).is_some() {
                                     if let Some(mut entity_commands) =
@@ -1101,6 +1124,13 @@ fn update_widgets(
                         entity_mut.remove::<bevy::prelude::Children>();
                         entity_mut.despawn();
                     }
+                    // Remove state entity
+                    if let Some(state_entity) = widget_state.remove(entity.0) {
+                        if let Some(mut entity_mut) = world.get_entity_mut(state_entity) {
+                            entity_mut.remove_parent();
+                            entity_mut.despawn_recursive();
+                        }
+                    }
                 }
             }
         }
@@ -1163,7 +1193,9 @@ fn update_widget(
                 } else {
                     let target = world.spawn_empty().insert(PreviousWidget).id();
                     if let Some(parent_id) = old_parent_entity {
-                        world.entity_mut(parent_id).add_child(target);
+                        if let Some(mut entity_mut) = world.get_entity_mut(parent_id) {
+                            entity_mut.add_child(target);
+                        }
                     }
                     cloned_widget_entities.insert(entity.0, target);
                     target
-- 
GitLab