Skip to content

Allow ImageNode with a texture atlas to be construct in BSN, fixes #24889#24965

Open
bitblocks-dev wants to merge 2 commits into
bevyengine:mainfrom
bitblocks-dev:main
Open

Allow ImageNode with a texture atlas to be construct in BSN, fixes #24889#24965
bitblocks-dev wants to merge 2 commits into
bevyengine:mainfrom
bitblocks-dev:main

Conversation

@bitblocks-dev

Copy link
Copy Markdown

Objective

Allow ImageNode with a texture atlas to be construct in BSN, fixes #24889

Solution

Replaces

pub struct ImageNode {
  #[template(built_in)]
  pub texture_atlas: Option<TextureAtlas>,
  // -- snip --
}

with

pub struct ImageNode {
  #[template(OptionTemplate<TextureAtlasTemplate>)]
  pub texture_atlas: Option<TextureAtlas>,
  // -- snip --
}

which makes it possible to construct ImageNode with a texture atlas, though the ergonomics could use some work.

Testing

Tested using the following code, adapted from the UI Texture Atlas Slice example.

Click to view
use bevy::{
    color::palettes::css::{GOLD, ORANGE},
    image::TextureAtlasTemplate,
    prelude::*,
    ui::widget::NodeImageMode,
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, button_system)
        .run();
}

fn button_system(
    mut interaction_query: Query<
        (&Interaction, &Children, &mut ImageNode),
        (Changed<Interaction>, With<Button>),
    >,
    mut text_query: Query<&mut Text>,
) {
    for (interaction, children, mut image) in &mut interaction_query {
        let mut text = text_query.get_mut(children[0]).unwrap();
        match *interaction {
            Interaction::Pressed => {
                **text = "Press".to_string();
                if let Some(atlas) = &mut image.texture_atlas {
                    atlas.index = (atlas.index + 1) % 30;
                }
                image.color = GOLD.into();
            }
            Interaction::Hovered => {
                **text = "Hover".to_string();
                image.color = ORANGE.into();
            }
            Interaction::None => {
                **text = "Button".to_string();
                image.color = Color::WHITE;
            }
        }
    }
}

fn setup(mut commands: Commands) {
    // ui camera
    commands.spawn(Camera2d);

    commands.spawn_scene(bsn! {
       Node {
            width: percent(100),
            height: percent(100),
            align_items: AlignItems::Center,
            justify_content: JustifyContent::Center,
        }
        Children [
            Button
            ImageNode {
                image: "textures/fantasy_ui_borders/border_sheet.png",
                texture_atlas: Option::<TextureAtlasTemplate>::Some(TextureAtlasTemplate { layout: asset_value(TextureAtlasLayout::from_grid(UVec2::new(50,50), 6, 6, Some(UVec2::splat(2)), None)), index: 0 })
                image_mode: NodeImageMode::Sliced(
                TextureSlicer {
                    border: BorderRect::all(24.0),
                    center_scale_mode: SliceScaleMode::Stretch,
                    sides_scale_mode: SliceScaleMode::Stretch,
                    max_corner_scale: 1.0,
                }),
            }
            Node {
                width: px(300.0),
                height: px(150.0),
                // horizontally center child text
                justify_content: JustifyContent::Center,
                // vertically center child text
                align_items: AlignItems::Center,
                margin: UiRect::all(px(20.0)),
            }
            Children [
                Text::new("Button"),
                TextColor(Color::srgb(0.9, 0.9, 0.9)),
            ]
        ]
    });
}

@github-actions

Copy link
Copy Markdown
Contributor

Welcome, new contributor!

Please make sure you've read our contributing guide, as well as our policy regarding AI usage, and we look forward to reviewing your pull request shortly ✨

/// This defaults to a [`TRANSPARENT_IMAGE_HANDLE`], which points to a fully transparent 1x1 texture.
pub image: Handle<Image>,
/// The (optional) texture atlas used to render the image.
#[template(built_in)]

@kfc35 kfc35 Jul 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, does this mean something is wrong with built_in? As far as I know from the original PR https://github.com/bevyengine/bevy/pull/23699/changes#diff-227e59a8188aa92faa1fb6bd502828d6aad148bebff25ee72528b408d6c5078dL26, this was meant to replace the verbosity of OptionTemplate<TextureAtlasTemplate>

@bitblocks-dev bitblocks-dev Jul 14, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? I'm not super familiar with how built_in functions... I just tried replacing it and that worked. Definitely worth looking into

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI @cart

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange yeah built_in exists to avoid needing to manually specify final template in these cases. I'll need to look into it.

Its worth noting that my WIP Assets as Entities branch removes built_in completely and generally reduces the weirdness factor for these types by removing the need for a separate OptionTemplate.

@kfc35 kfc35 added A-Scenes Composing and serializing ECS objects S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jul 14, 2026
@kfc35
kfc35 requested a review from cart July 14, 2026 02:56
@kfc35 kfc35 added the C-Bug An unexpected or incorrect behavior label Jul 14, 2026
@alice-i-cecile alice-i-cecile added S-Needs-Investigation This issue requires detective work to figure out what's going wrong and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Scenes Composing and serializing ECS objects C-Bug An unexpected or incorrect behavior S-Needs-Investigation This issue requires detective work to figure out what's going wrong

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to specify texture_atlas in bsn! macro

4 participants