diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 57cf261d3..895f3c9bb 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,8 @@ # Renzora Engine `r1-alpha8` +## 2026-10-07 21:03 +- fix(hierarchy): Duplicate in the hierarchy right-click menu copies every component, like Ctrl+D, instead of making an empty entity at the origin + ## 2026-09-18 16:27 - fix(game-ui): an `expand` canvas previewed over the viewport lays out like the shipped game, so edge-anchored UI reaches the edge - fix(game-ui): a canvas root no longer keeps a preview scale that was saved into a scene, which shrank the UI in an exported game diff --git a/crates/renzora_hierarchy/src/native/context_menu.rs b/crates/renzora_hierarchy/src/native/context_menu.rs index 40ee283c3..57b1be68c 100644 --- a/crates/renzora_hierarchy/src/native/context_menu.rs +++ b/crates/renzora_hierarchy/src/native/context_menu.rs @@ -316,16 +316,21 @@ fn add_child(world: &mut World, target: Entity) { } } +/// Deep-clones `target` through Bevy's `clone_and_spawn`, the same path the +/// Ctrl+D shortcut uses (`renzora_gizmo::shortcuts::duplicate_entities`), so +/// the menu and keyboard produce the same object. This used to spawn only a +/// `Name` and a default `Transform`: the "copy" had no mesh, collider or +/// gameplay components and sat at the origin. fn duplicate(world: &mut World, target: Entity) { - let parent = world.get::(target).map(|c| c.parent()); + let Ok(mut src) = world.get_entity_mut(target) else { + return; + }; + let new_entity = src.clone_and_spawn(); let name = world - .get::(target) + .get::(new_entity) .map(|n| format!("{} (Copy)", n.as_str())) .unwrap_or_else(|| "Entity (Copy)".to_string()); - let new_entity = world.spawn((Name::new(name), Transform::default())).id(); - if let Some(p) = parent { - world.entity_mut(new_entity).set_parent_in_place(p); - } + world.entity_mut(new_entity).insert(Name::new(name)); if let Some(sel) = world.get_resource::() { sel.set(Some(new_entity)); }