1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Showcases sprite 9 slice scaling and tiling features, enabling usage of
//! sprites in multiple resolutions while keeping it in proportion
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                resolution: (1350.0, 700.0).into(),
                ..default()
            }),
            ..default()
        }))
        .add_systems(Startup, setup)
        .run();
}

fn spawn_sprites(
    commands: &mut Commands,
    texture_handle: Handle<Image>,
    mut position: Vec3,
    slice_border: f32,
    style: TextStyle,
    gap: f32,
) {
    let cases = [
        // Reference sprite
        ("Original texture", style.clone(), Vec2::splat(100.0), None),
        // Scaled regular sprite
        (
            "Stretched texture",
            style.clone(),
            Vec2::new(100.0, 200.0),
            None,
        ),
        // Stretched Scaled sliced sprite
        (
            "Stretched and sliced",
            style.clone(),
            Vec2::new(100.0, 200.0),
            Some(ImageScaleMode::Sliced(TextureSlicer {
                border: BorderRect::square(slice_border),
                center_scale_mode: SliceScaleMode::Stretch,
                ..default()
            })),
        ),
        // Scaled sliced sprite
        (
            "Sliced and Tiled",
            style.clone(),
            Vec2::new(100.0, 200.0),
            Some(ImageScaleMode::Sliced(TextureSlicer {
                border: BorderRect::square(slice_border),
                center_scale_mode: SliceScaleMode::Tile { stretch_value: 0.5 },
                sides_scale_mode: SliceScaleMode::Tile { stretch_value: 0.2 },
                ..default()
            })),
        ),
        // Scaled sliced sprite horizontally
        (
            "Sliced and Tiled",
            style.clone(),
            Vec2::new(300.0, 200.0),
            Some(ImageScaleMode::Sliced(TextureSlicer {
                border: BorderRect::square(slice_border),
                center_scale_mode: SliceScaleMode::Tile { stretch_value: 0.2 },
                sides_scale_mode: SliceScaleMode::Tile { stretch_value: 0.3 },
                ..default()
            })),
        ),
        // Scaled sliced sprite horizontally with max scale
        (
            "Sliced and Tiled with corner constraint",
            style,
            Vec2::new(300.0, 200.0),
            Some(ImageScaleMode::Sliced(TextureSlicer {
                border: BorderRect::square(slice_border),
                center_scale_mode: SliceScaleMode::Tile { stretch_value: 0.1 },
                sides_scale_mode: SliceScaleMode::Tile { stretch_value: 0.2 },
                max_corner_scale: 0.2,
            })),
        ),
    ];

    for (label, text_style, size, scale_mode) in cases {
        position.x += 0.5 * size.x;
        let mut cmd = commands.spawn(SpriteBundle {
            transform: Transform::from_translation(position),
            texture: texture_handle.clone(),
            sprite: Sprite {
                custom_size: Some(size),
                ..default()
            },
            ..default()
        });
        if let Some(scale_mode) = scale_mode {
            cmd.insert(scale_mode);
        }
        cmd.with_children(|builder| {
            builder.spawn(Text2dBundle {
                text: Text::from_section(label, text_style).with_justify(JustifyText::Center),
                transform: Transform::from_xyz(0., -0.5 * size.y - 10., 0.0),
                text_anchor: bevy::sprite::Anchor::TopCenter,
                ..default()
            });
        });
        position.x += 0.5 * size.x + gap;
    }
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2dBundle::default());
    let font = asset_server.load("fonts/FiraSans-Bold.ttf");
    let style = TextStyle {
        font: font.clone(),
        font_size: 16.0,
        ..default()
    };

    // Load textures
    let handle_1 = asset_server.load("textures/slice_square.png");
    let handle_2 = asset_server.load("textures/slice_square_2.png");

    spawn_sprites(
        &mut commands,
        handle_1,
        Vec3::new(-600.0, 200.0, 0.0),
        200.0,
        style.clone(),
        50.,
    );

    spawn_sprites(
        &mut commands,
        handle_2,
        Vec3::new(-600.0, -200.0, 0.0),
        80.0,
        style,
        50.,
    );
}