rustbevybevy-v0.13.0

How to swap color materials in an update call?


During bevy setup, I've spawned multiple rectangles with two different colors. How do I update these rectangles with a new color material?

// in setup
commands.spawn(
    (MaterialMesh2dBundle {
        mesh: Mesh2dHandle(meshes.add(Rectangle::new(10., 10.))),
        material: if dull_world.is_live(row_index, col_index) {
            materials.add(Color::PURPLE)
        } else {
            materials.add(Color::GREEN)
        },
        transform: Transform::from_xyz(
            (row_index as f32 - row_len as f32 / 2.) * 10.,
            (col_index as f32 - col_len as f32 / 2.) * 10.,
            0.0,
        ),
        ..default()
    }),
);

full code


Solution

  • One way to accomplish this is to reuse the material handles you're creating by inserting them as Resources.

    Then during your update call, query the entities that match Query<&mut Handle<ColorMaterial>> with the resource you want Res<CellDeadColor>. Since the handles exist already, you simply need to clone them and apply them to the color material handler.

    // global
    #[derive(Resource)]
    struct CellDeadColor(Handle<ColorMaterial>);
    
    #[derive(Resource)]
    struct CellLiveColor(Handle<ColorMaterial>);
    
    // setup
    let live_color_handle = materials.add(Color::GREEN); // Handle<ColorMaterial>
    let dead_color_handle = materials.add(Color::PURPLE); // Handle<ColorMaterial>
    
    let cell_live_color = CellLiveColor(live_color_handle.clone());
    let cell_dead_color = CellDeadColor(dead_color_handle.clone());
    
    commands.insert_resource(cell_live_color);
    commands.insert_resource(cell_dead_color);
    
    commands.spawn(
        (MaterialMesh2dBundle {
            mesh: Mesh2dHandle(meshes.add(Rectangle::new(10., 10.))),
            material: if dull_world.is_live(row_index, col_index) {
                live_color_handle.clone()
            } else {
                dead_color_handle.clone()
            },
            transform: Transform::from_xyz(
                (row_index as f32 - row_len as f32 / 2.) * 10.,
                (col_index as f32 - col_len as f32 / 2.) * 10.,
                0.0,
            ),
            ..default()
        }),
    );
    
    // update
    fn render_world(
        mut q_entities: Query<(&mut Handle<ColorMaterial>, &Cell)>,
        q_dull_world: Query<&DullWorld>,
        q_dead_cell_color: Res<CellDeadColor>,
        q_live_cell_color: Res<CellLiveColor>,
    ) {
        let dull_world = q_dull_world.iter().next().unwrap();
        for (mut entity, cell) in q_entities.iter_mut() {
            if dull_world.is_live(cell.row_index, cell.col_index) {
                *entity = q_dead_cell_color.0.clone();
            } else {
                *entity = q_live_cell_color.0.clone();
            };
        }
    }