Skip to content

Commit 6f236bf

Browse files
Guard against VisibilityClass being duplicated while cloning (#21069)
# Objective - This is the second attempt at "Fixes #20884" after conversation in #20891 ## Solution - I followed the approach discussed in #20891 to add `#[component(clone_behavior=Ignore)]` to avoid cloning this Component ## Testing - I tested the change with a simple repro. I'm not sure if I can unit test just the existence of this line but I'll see if I can and update accordingly. ```rust use bevy::{prelude::*, render::view::NoIndirectDrawing}; fn main() { App::new() .insert_resource(ClearColor(Color::BLACK)) .add_plugins(DefaultPlugins) .add_systems(Startup, startup) .run(); } fn startup( mut cmd: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<StandardMaterial>>, mut al: ResMut<AmbientLight>, ) { al.brightness = 5000.; cmd.spawn(( Mesh3d(meshes.add(Cuboid::from_size(Vec3::new(4., 0.5, 0.1)))), MeshMaterial3d(materials.add(Color::srgb(1., 1., 0.))), Transform::from_xyz(0., 0., -2.), )); let mut id = cmd.spawn(( Mesh3d(meshes.add(Cuboid::from_length(1.))), MeshMaterial3d(materials.add(Color::srgba(0., 0., 1., 0.5))), Transform::from_xyz(-0.5, 0., 0.), )); id.clone_and_spawn() .insert(Transform::from_xyz(0.5, 0., 0.)); cmd.spawn(( Camera3d::default(), Transform::from_xyz(0., 0., 10.).looking_at(Vec3::ZERO, Vec3::Y), NoIndirectDrawing, )); } ``` ## Showcase Before <img width="178" height="202" alt="486232152-9f8685f6-fbc3-4bc1-b9bd-7e28177cc901" src="https://github.com/user-attachments/assets/2bca4f28-b956-49dc-83b4-edefef6ca595" /> After <img width="120" height="173" alt="486232412-bafd5e4a-69be-4249-894a-5f03dfe28b63" src="https://github.com/user-attachments/assets/1b911bb6-01c4-451a-b010-20aab505217e" /> Co-authored-by: Dimitrios Loukadakis <[email protected]>
1 parent 2588452 commit 6f236bf

File tree

1 file changed

+28
-0
lines changed
  • crates/bevy_camera/src/visibility

1 file changed

+28
-0
lines changed

crates/bevy_camera/src/visibility/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,16 @@ impl InheritedVisibility {
150150
/// When adding a new renderable component, you'll typically want to write an
151151
/// add-component hook that adds the type ID of that component to the
152152
/// [`VisibilityClass`] array. See `custom_phase_item` for an example.
153+
///
154+
/// `VisibilityClass` is automatically added by a hook on the `Mesh3d` and
155+
/// `Mesh2d` components. To avoid duplicating the `VisibilityClass` and
156+
/// causing issues when cloning, we use `#[component(clone_behavior=Ignore)]`
153157
//
154158
// Note: This can't be a `ComponentId` because the visibility classes are copied
155159
// into the render world, and component IDs are per-world.
156160
#[derive(Clone, Component, Default, Reflect, Deref, DerefMut)]
157161
#[reflect(Component, Default, Clone)]
162+
#[component(clone_behavior=Ignore)]
158163
pub struct VisibilityClass(pub SmallVec<[TypeId; 1]>);
159164

160165
/// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering.
@@ -988,4 +993,27 @@ mod test {
988993
assert_eq!(1, size_of::<Visibility>());
989994
assert_eq!(1, size_of::<Option<Visibility>>());
990995
}
996+
997+
#[derive(Component, Default, Clone, Reflect)]
998+
#[require(VisibilityClass)]
999+
#[reflect(Component, Default, Clone)]
1000+
#[component(on_add = add_visibility_class::<Self>)]
1001+
struct TestVisibilityClassHook;
1002+
1003+
#[test]
1004+
fn test_add_visibility_class_hook() {
1005+
let mut world = World::new();
1006+
let entity = world.spawn(TestVisibilityClassHook).id();
1007+
let entity_clone = world.spawn_empty().id();
1008+
world
1009+
.entity_mut(entity)
1010+
.clone_with_opt_out(entity_clone, |_| {});
1011+
1012+
let entity_visibility_class = world.entity(entity).get::<VisibilityClass>().unwrap();
1013+
assert_eq!(entity_visibility_class.len(), 1);
1014+
1015+
let entity_clone_visibility_class =
1016+
world.entity(entity_clone).get::<VisibilityClass>().unwrap();
1017+
assert_eq!(entity_clone_visibility_class.len(), 1);
1018+
}
9911019
}

0 commit comments

Comments
 (0)