Commit Graph

29 Commits

Author SHA1 Message Date
ickshonpe b00ff93c87 Remove new_with_ prefix from the TextLayout constuctor functions (#24049)
# Objective

Remove the `new_with_` prefixes from the `TextLayout` constuctor
functions. Generally, the "new" part is redundant and "with" is used by
fluent APIs.

## Solution

Just delete the prefixes, shorten the names (all on `TextLayout`).
* `new_with_justify` -> `justify`
* `new_with_linebreak` -> `linebreak`
* `new_with_no_wrap` -> `no_wrap`
2026-05-01 21:08:18 +00:00
Alice Cecile 36a97620df Add white furnace analog for 2D color consistency (#23589)
# Objective

Create a regression test for
https://github.com/bevyengine/bevy/issues/23577.

## Solution

Copy the white furnace test idea by spawning a bunch of 2D things with
exactly the same color.

Split out from #23584.

## Testing

`cargo run -example testbed_2d`. Press space to get to the example
that's all grey.

Locally, this is all one uniform grey for me: I could not reproduce
#23577.

Still, this is a useful property to test for!
2026-03-31 22:52:46 +00:00
ickshonpe df5cdd0faa Despawn atlas sprites on scene exit in testbed_2d (#23133)
# Objective

Some cleanup is missing from the 2d testbed's `TextureAtlasBuilder`
scene.

## Solution

Add `DespawnOnExit(super::Scene::TextureAtlasBuilder)` to the atlas
sprites.
2026-03-02 19:00:13 +00:00
ickshonpe 1aedbf36d1 Fix the gizmo colors in testbed_2d's texture_atlas_builder scene (#23146)
# Objective

Fix the gizmo colours in testbed_2d instead of basing them on entity
ids.

## Solution

```rust
ShowAabbGizmo {
    color: Some(Color::WHITE),
}
```
2026-03-01 20:14:06 +00:00
ickshonpe b03922d484 testbed_2d texture atlas builder scene (#23074)
# Objective

Add a scene displaying the output from `TextureAtlasBuilder`.

## Solution

Add a scene showing the atlases textures and padding and how it affects
the sub images when they are drawn.

## Testing

```
cargo run --example testbed_2d -- textureatlasbuilder
```
2026-02-24 01:15:57 +00:00
Chintan Bhatt 7c153070c0 Adds text gizmos to testbeds (#23064)
# Objective

- Fixed both #23058 and #23059 

## Solution

- Adds text gizmos to the 2D and 3D testbed examples

## Testing

Tested on Windows 11/Nvidia/Vulkan

---

## Showcase

<details>
  <summary>Click to view showcase</summary>

### testbed_2d

<img width="1282" height="752" alt="image"
src="https://github.com/user-attachments/assets/ce20cf8f-c6f0-49be-8290-9f912c144f65"
/>


### testbed_3d

<img width="1282" height="752" alt="image"
src="https://github.com/user-attachments/assets/2de280bd-bf2f-4335-a7ba-c25fc9a53d25"
/>


</details>
2026-02-20 05:46:01 +00:00
ickshonpe 6ca4769128 Minimal responsive FontSize support (#22614)
# Objective

Add responsive font sizes supporting rem and viewport units to
`bevy_text` with minimal changes to the APIs and systems.

## Solution

Introduce a new `FontSize` enum:

```rust
pub enum FontSize {
    /// Font Size in logical pixels.
    Px(f32),
    /// Font size as a percentage of the viewport width.
    Vw(f32),
    /// Font size as a percentage of the viewport height.
    Vh(f32),
    /// Font size as a percentage of the smaller of the viewport width and height.
    VMin(f32),
    /// Font size as a percentage of the larger of the viewport width and height.
    VMax(f32),
    /// Font Size relative to the value of the `RemSize` resource.
    Rem(f32),
}
```

This replaces the `f32` value of `TextFont`'s `font_size` field.

The viewport variants work the same way as their respective `Val`
counterparts.

`Rem` values are multiplied by the value of the `RemSize` resource
(which newtypes an `f32`).

`FontSize` provides an `eval` method that takes a logical viewport size
and rem base size and returns an `f32` logical font size. The resolved
logical font size is then written into the `Attributes` passed to Cosmic
Text by `TextPipeline::update_buffer`.

Any text implementation using `bevy_text` must now provide viewport and
rem base values when calling `TextPipeline::update_buffer` or
`create_measure`.

`Text2d` uses the size of the primary window to resolve viewport values
(or `Vec2::splat(1000)` if no primary window is found). This is a
deliberate compromise, a single `Text2d` can be rendered to multiple
viewports using `RenderLayers`, so it's difficult to find a rule for
which viewport size should be chosen.

### Change detection 

`ComputedTextBlock` has two new fields: `uses_viewport_sizes` and
`uses_rem_sizes`, which are set to true in `TextPipeline::update_buffer`
iff any text section in the block uses viewport or rem font sizes,
respectively.

The `ComputedTextBlock::needs_rerender` method has been modified to take
take two bool parameters:
```rust
    pub fn needs_rerender(
        &self,
        is_viewport_size_changed: bool,
        is_rem_size_changed: bool,
    ) -> bool {
        self.needs_rerender
            || (is_viewport_size_changed && self.uses_viewport_sizes)
            || (is_rem_size_changed && self.uses_rem_sizes)
    }
 ```
This ensures that text reupdates will also be scheduled if one of the text section's uses a viewport font size and the local viewport size changed, or if one of the text section's uses a rem font size and the rem size changed.

#### Limitations

There are some limitations because we don't have any sort of font style inheritance yet:

* "rem" units aren't proper rem units, and just based on the value of a resource. 
* "em" units are resolved based on inherited font size, so can't be implemented without inheritance support.

#### Notes

* This PR is quite small and not very technical. Reviewers don't need to be especially familiar with `bevy_text`. Most of the changes are to the examples.

* We could consider using `Val` instead of `FontSize`, then we could use `Val`'s constructor functions which would be much nicer, but some variants might not have sensible interpretations in both UI and Text2d contexts. Also we'd have to make `Val` accessible to `bevy_text`.

## Testing

The changes to the text systems are relatively trivial and easy to understand.  I already added a minor change to the `text` example to use `Vh` font size for the "hello bevy" text in the bottom right corner. If you change the size of the window, you should see the text change size in response. The text initially flickers before it updates because of some unrelated asset/image changes that mean that font textures aren't ready until the frame after the text update that changes the font size.

Most of the example migrations were automated using regular expressions, and there are bound to be mistakes in those changes. It's infeasible to check every single example thoroughly, but it's early enough in the release cycle that I don't think we should be too worried if a few bugs slip in.

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-02-02 22:52:33 +00:00
ickshonpe e5d4dfd7a6 Minimal Font Families, Font Queries, Collections, System Fonts, Stretch, and Slant support (#22156)
# Objective

Implement support for the remaining missing text features with minimal
changes.

## Solution

`TextFont` has been expanded to include new fields:
```rust
pub struct TextFont {
    pub font: FontSource,
    pub font_size: f32,
    pub weight: FontWeight,
    pub width: FontWidth,
    pub style: FontStyle,
    pub font_smoothing: FontSmoothing,
    pub font_features: FontFeatures,
}
```

FontSource has two variants: Handle, which identifies a font by asset
handle, and Family, which selects a font by its family name.

`FontWidth` is a newtype struct representing OpenType font stretch
classifications ranging from ULTRA_CONDENSED (50%) to ULTRA_EXPANDED
(200%).

`FontStyle` is an enum used to set the slant style of a font, either
`Normal`, `Italic`, or `Oblique`.

The system font support is very barebones. You load them using the
`CosmicFontSystem` resource:
```rust
font_system.db_mut().load_system_fonts()
```
Then they are available to be selected by family name using
`FontSource::Family`.

### Other changes

* `TextPipelines`'s `glyph_info` field has been removed. There is no
need to collect the section infos or perform any querys during text
layout updates, so that code has been removed as well.

* `update_text_layout_info` used some `try_for_each` with some nested
closures which was unnecessarily complicated again. They've been
replaced with a regular for loop.

* After font assets are loaded there's a new system
`load_font_assets_into_fontdb_system` that automatically adds them to
cosmic text's font database. Then they are available to be looked up by
family name as well as by asset handle.

* There aren't are performance motivated changes but layout updates seem
to be overall significantly more efficient now, with a slight regression
for very large numbers of short, single section text entities.

* Font texture atlases are no longer automatically cleared when the font
asset they were generated from is removed. There is no way to remove
individual fonts from cosmic text's `FontSystem`, so the font is still
accessible using the family name with `FontSource::family` and removing
the text atlases naively could cause a panic since rendering expects
them to be present.

## Testing

```
cargo run --example font_query
```
---

## Showcase

<img width="1229" height="591" alt="font-query"
src="https://github.com/user-attachments/assets/23f5aaa2-fdb8-4448-9b4e-9d65d6431107"
/>

---------

Co-authored-by: Thierry Berger <contact@thierryberger.com>
2026-01-03 22:38:53 +00:00
François Mockers 730b002260 fix testbeds with argh in wasm (#22339)
# Objective

- #22223  used argh in the testbed examples
- this compile in wasm but crashes when running them

## Solution

- Fix it like the other examples using argh
2026-01-01 19:47:31 +00:00
panpanpro888 9f02248af4 Add command line option to choose a starting scene in the `testbed_*' examples (#22223)
# Objective

- Fixes #22218

## Solution

- Use `argh` to check if you passed a scene name, and if you did, start
on that one instead of the default

## Testing

- Tested on my local machine, I don't see a reason why it would change
between different machines and/or platforms

---------

Co-authored-by: Bayley Foster <43776524+apekros@users.noreply.github.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-12-31 22:59:49 +00:00
shivanandu b58ecf2ac3 Add sprite slicing scene to testbed_2d example (#22089)
# Objective

- Sprite slicing doesn't have any example with the screenshot CI.
- Fixes #22083

## Solution

- Added a new `sprite_slicing` module to `examples/testbed/2d.rs`

## Testing
- Ran the testbed with `cargo run --example testbed_2d`
- Cycled through all scenes using spacebar
- Verified the sprite slicing scene displays correctly with both
original and sliced sprites
- Confirmed labels and positioning are correct

---

## Showcase

<img width="1372" height="755" alt="Screenshot From 2025-12-11 15-41-23"
src="https://github.com/user-attachments/assets/8f5a6223-78bb-4670-b23e-280e003df324"
/>
2025-12-14 21:26:13 +00:00
atlv f6b77e4e49 bevy_post_process (#20778)
# Objective

Split out post process effects from bevy_core_pipeline because they are
not core pipelines.

## Solution

@IceSentry proposed something like this, not sure if the split is
exactly as he envisioned but this seems reasonable to me.

The goal is to move absolutely everything possible out of
bevy_core_pipelines to unblock bevy_pbr/bevy_sprite_render compilation.

Future PRs may attempt to move more little bits out.

## Testing
2025-09-05 04:26:08 +00:00
Jan Hohenheim b43a73df3f Rename DespawnOnExitState to DespawnOnExit (#20872)
# Objective

- `StateScoped` was renamed to `DespawnOnExitState`, and we introduced
`DespawnOnEnterState`
- This is redundant: the type it wraps is already a state
- Often, state enums have `State` in their names, leading to stutter:
`DespawnOnExitState(GameState::Gameplay)`
- This component is *very* common in games. The longer name makes it
clunkier to use, so we should be careful when expanding it. I think the
added clarity is good, but we can do better.

## Solution

- Compromise to `DespawnOnExit`
- Do the same for `DespawnOnEnter`

## Testing

- CI
2025-09-04 21:13:46 +00:00
Amedo 6eb011c30c Replace from_ constructors on TextFont with From impls (#20450)
# Objective

- Closes #20353

## Solution

- Removed `TextFont::from_font` and `TextFont::from_line_height`.
- Updated `examples/testbed/2d.rs` to use the `Form` impl.
- Added migration guide.
2025-09-04 20:05:32 +00:00
theotherphil 2e259713c2 Bug fix in Gizmo grid (#19697)
# Objective

Fix https://github.com/bevyengine/bevy/issues/19480

## Solution

Fix calculation of line counts in each direction

## Testing

Added grids to the gizmos screens of testbed/example_3d and
testbed/example_2d.

<img width="1246" alt="image"
src="https://github.com/user-attachments/assets/56924e44-1b54-43dc-9cf0-dba390570f3b"
/>

<img width="1246" alt="image"
src="https://github.com/user-attachments/assets/566c3d1b-64aa-43bb-a1db-c2e41de2a7a6"
/>
2025-07-29 20:18:55 +00:00
ickshonpe f774d6b7ed Text2d bounding box fix (#20148)
# Objective

`calculate_bounds_text2d` generates `Aabb`s with the wrong size and
position for `Text2d` entities with `TextBounds`, which breaks culling.

## Solution

Calculate the correct bounds.

Fixes #20145

## Testing

```
cargo run --example testbed_2d
```

#### main
<img width="661" height="469" alt="text2daabb"
src="https://github.com/user-attachments/assets/c10b64ed-6e0d-4c4e-a81d-6ae2248d752a"
/>

#### This PR

<img width="441" height="308" alt="fixed-text2d-aabbs"
src="https://github.com/user-attachments/assets/bc715bf0-b77f-4149-9c6d-a5a8c1982780"
/>
2025-07-15 17:14:49 +00:00
ickshonpe 02fa833be1 Rename JustifyText to Justify (#19522)
# Objective

Rename `JustifyText`:

* The name `JustifyText` is just ugly.
* It's inconsistent since no other `bevy_text` types have a `Text-`
suffix, only prefix.
* It's inconsistent with the other text layout enum `Linebreak` which
doesn't have a prefix or suffix.

Fixes #19521.

## Solution

Rename `JustifyText` to `Justify`.

Without other context, it's natural to assume the name `Justify` refers
to text justification.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-06-09 19:59:48 +00:00
François Mockers 8a223be651 Enable state scoped entities by default (#19354)
# Objective

- Enable state scoped entities by default
- Provide a way to disable it when needed

---------

Co-authored-by: Ben Frankel <ben.frankel7@gmail.com>
2025-05-26 20:26:41 +00:00
Emerson Coskey 7ab00ca185 Split Camera.hdr out into a new component (#18873)
# Objective

- Simplify `Camera` initialization
- allow effects to require HDR

## Solution

- Split out `Camera.hdr` into a marker `Hdr` component

## Testing

- ran `bloom_3d` example

---

## Showcase

```rs
// before
commands.spawn((
  Camera3d
  Camera {
    hdr: true
    ..Default::default()
  }
))

// after
commands.spawn((Camera3d, Hdr));

// other rendering components can require that the camera enables hdr!
// currently implemented for Bloom, AutoExposure, and Atmosphere.
#[require(Hdr)]
pub struct Bloom;
```
2025-05-26 19:24:45 +00:00
ickshonpe 2b59ab8e2d Fix Anchor component inconsistancies (#18393)
## Objective

Fix the misleading 2d anchor API where `Anchor` is a component and
required by `Text2d` but is stored on a field for sprites.

Fixes #18367

## Solution

Remove the `anchor` field from `Sprite` and require `Anchor` instead.

## Migration Guide

The `anchor` field has been removed from `Sprite`. Instead the `Anchor`
component is now a required component on `Sprite`.
2025-05-21 15:32:04 +00:00
mgi388 7a1fcb7fe7 Rename StateScoped to DespawnOnExitState and add DespawnOnEnterState (#18818)
# Objective

- Alternative to and builds on top of #16284.
- Fixes #15849.

## Solution

- Rename component `StateScoped` to `DespawnOnExitState`.
- Rename system `clear_state_scoped_entities` to
`despawn_entities_on_exit_state`.
- Add `DespawnOnEnterState` and `despawn_entities_on_enter_state` which
is the `OnEnter` equivalent.

> [!NOTE]
> Compared to #16284, the main change is that I did the rename in such a
way as to keep the terms `OnExit` and `OnEnter` together. In my own
game, I was adding `VisibleOnEnterState` and `HiddenOnExitState` and
when naming those, I kept the `OnExit` and `OnEnter` together. When I
checked #16284 it stood out to me that the naming was a bit awkward.
Putting the `State` in the middle and breaking up `OnEnter` and `OnExit`
also breaks searching for those terms.

## Open questions

1. Should we split `enable_state_scoped_entities` into two functions,
one for the `OnEnter` and one for the `OnExit`? I personally have zero
need thus far for the `OnEnter` version, so I'd be interested in not
having this enabled unless I ask for it.
2. If yes to 1., should we follow my lead in my `Visibility` state
components (see below) and name these
`app.enable_despawn_entities_on_enter_state()` and
`app.enable_despawn_entities_on_exit_state()`, which IMO says what it
does on the tin?

## Testing

Ran all changed examples.

## Side note: `VisibleOnEnterState` and `HiddenOnExitState`

For reference to anyone else and to help with the open questions, I'm
including the code I wrote for controlling entity visibility when a
state is entered/exited.

<details>
<summary>visibility.rs</summary>

```rust
use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use bevy_reflect::prelude::*;
use bevy_render::prelude::*;
use bevy_state::{prelude::*, state::StateTransitionSteps};
use tracing::*;

pub trait AppExtStates {
    fn enable_visible_entities_on_enter_state<S: States>(&mut self) -> &mut Self;

    fn enable_hidden_entities_on_exit_state<S: States>(&mut self) -> &mut Self;
}

impl AppExtStates for App {
    fn enable_visible_entities_on_enter_state<S: States>(&mut self) -> &mut Self {
        self.main_mut()
            .enable_visible_entities_on_enter_state::<S>();
        self
    }

    fn enable_hidden_entities_on_exit_state<S: States>(&mut self) -> &mut Self {
        self.main_mut().enable_hidden_entities_on_exit_state::<S>();
        self
    }
}

impl AppExtStates for SubApp {
    fn enable_visible_entities_on_enter_state<S: States>(&mut self) -> &mut Self {
        if !self
            .world()
            .contains_resource::<Events<StateTransitionEvent<S>>>()
        {
            let name = core::any::type_name::<S>();
            warn!("Visible entities on enter state are enabled for state `{}`, but the state isn't installed in the app!", name);
        }
        // We work with [`StateTransition`] in set
        // [`StateTransitionSteps::ExitSchedules`] as opposed to [`OnExit`],
        // because [`OnExit`] only runs for one specific variant of the state.
        self.add_systems(
            StateTransition,
            update_to_visible_on_enter_state::<S>.in_set(StateTransitionSteps::ExitSchedules),
        )
    }

    fn enable_hidden_entities_on_exit_state<S: States>(&mut self) -> &mut Self {
        if !self
            .world()
            .contains_resource::<Events<StateTransitionEvent<S>>>()
        {
            let name = core::any::type_name::<S>();
            warn!("Hidden entities on exit state are enabled for state `{}`, but the state isn't installed in the app!", name);
        }
        // We work with [`StateTransition`] in set
        // [`StateTransitionSteps::ExitSchedules`] as opposed to [`OnExit`],
        // because [`OnExit`] only runs for one specific variant of the state.
        self.add_systems(
            StateTransition,
            update_to_hidden_on_exit_state::<S>.in_set(StateTransitionSteps::ExitSchedules),
        )
    }
}

#[derive(Clone, Component, Debug, Reflect)]
#[reflect(Component, Debug)]
pub struct VisibleOnEnterState<S: States>(pub S);

#[derive(Clone, Component, Debug, Reflect)]
#[reflect(Component, Debug)]
pub struct HiddenOnExitState<S: States>(pub S);

/// Makes entities marked with [`VisibleOnEnterState<S>`] visible when the state
/// `S` is entered.
pub fn update_to_visible_on_enter_state<S: States>(
    mut transitions: EventReader<StateTransitionEvent<S>>,
    mut query: Query<(&VisibleOnEnterState<S>, &mut Visibility)>,
) {
    // We use the latest event, because state machine internals generate at most
    // 1 transition event (per type) each frame. No event means no change
    // happened and we skip iterating all entities.
    let Some(transition) = transitions.read().last() else {
        return;
    };
    if transition.entered == transition.exited {
        return;
    }
    let Some(entered) = &transition.entered else {
        return;
    };
    for (binding, mut visibility) in query.iter_mut() {
        if binding.0 == *entered {
            visibility.set_if_neq(Visibility::Visible);
        }
    }
}

/// Makes entities marked with [`HiddenOnExitState<S>`] invisible when the state
/// `S` is exited.
pub fn update_to_hidden_on_exit_state<S: States>(
    mut transitions: EventReader<StateTransitionEvent<S>>,
    mut query: Query<(&HiddenOnExitState<S>, &mut Visibility)>,
) {
    // We use the latest event, because state machine internals generate at most
    // 1 transition event (per type) each frame. No event means no change
    // happened and we skip iterating all entities.
    let Some(transition) = transitions.read().last() else {
        return;
    };
    if transition.entered == transition.exited {
        return;
    }
    let Some(exited) = &transition.exited else {
        return;
    };
    for (binding, mut visibility) in query.iter_mut() {
        if binding.0 == *exited {
            visibility.set_if_neq(Visibility::Hidden);
        }
    }
}
```

</details>

---------

Co-authored-by: Benjamin Brienen <Benjamin.Brienen@outlook.com>
Co-authored-by: Ben Frankel <ben.frankel7@gmail.com>
2025-05-06 00:37:04 +00:00
ickshonpe f74abb1b89 Add sprite flipping to testbed_2d's sprite scene (#18537)
# Objective

Add sprite flipping to `testbed_2d`'s sprite scene

## Solution

Draw the sprite flipped in each axis and both axes.

Changed the sprite to the rectangular bevy banner with text and made the
images different colors.

## Testing
```
cargo run --example testbed_2d
```


![image](https://github.com/user-attachments/assets/dcfe687b-2f40-4417-bb20-6c892b425228)

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-03-25 21:14:17 +00:00
krunchington a090e2fd47 Update shader_prepass, testbed_2d, and first_person_view_model examples to use children! macro (#18270)
# Objective

Contributes to #18238 
Updates the `shader_prepass`, `testbed_2d` and `first_person_view_model`
examples to use the `children!` macro. I wanted to keep the PR small but
chose to do 3 examples since they were all limited in scope

## Solution

Updates examples to use the Improved Spawning API merged in
https://github.com/bevyengine/bevy/pull/17521

## Testing

- Did you test these changes? If so, how?
- Opened the examples before and after and verified the same behavior
was observed. I did this on Ubuntu 24.04.2 LTS using `--features
wayland`.
- Are there any parts that need more testing?
- Other OS's and features can't hurt, but this is such a small change it
shouldn't be a problem.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
  - Run the examples yourself with and without these changes.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - see above

---

## Showcase

n/a

## Migration Guide

n/a
2025-03-22 22:35:20 +00:00
ickshonpe 84b09b9398 Newtype Anchor (#18439)
# Objective

The `Anchor` component doesn't need to be a enum. The variants are just
mapped to `Vec2`s so it could be changed to a newtype with associated
const values, saving the space needed for the discriminator by the enum.

Also there was no benefit I think in hiding the underlying `Vec2`
representation of `Anchor`s.

Suggested by @atlv24.

Fixes #18459
Fixes #18460

## Solution

Change `Anchor` to a struct newtyping a `Vec2`, and its variants into
associated constants.

## Migration Guide

The anchor component has been changed from an enum to a struct newtyping
a `Vec2`. The `Custom` variant has been removed, instead to construct a
custom `Anchor` use its tuple constructor:
```rust
Sprite {
     anchor: Anchor(Vec2::new(0.25, 0.4)),
     ..default()
}
```
The other enum variants have been replaced with corresponding constants:
* `Anchor::BottomLeft` to `Anchor::BOTTOM_LEFT`
* `Anchor::Center` to `Anchor::CENTER`
* `Anchor::TopRight` to `Anchor::TOP_RIGHT`
* .. and so on for the remaining variants
2025-03-21 22:27:11 +00:00
François Mockers 4b457cc2ce Revert "don't use bevy_pbr for base bevy_gizmos plugin" (#18327)
# Objective

- #17581 broke gizmos
- Fixes #18325

## Solution

- Revert #17581 
- Add gizmos to testbed

## Testing

- Run any example with gizmos, it renders correctly
2025-03-17 22:23:42 +00:00
Rob Parrett 4a41525cd0 Add more to the 2d testbed for text (#18240)
# Objective

`Text2d` testing hasn't been as thorough as text in the UI, and it
suffered a bunch of bugs / perf issues in recent cycles.

## Solution

Add some more `Text2d` scenarios to the 2d testbed to catch bugs,
testing bounded and unbounded text with various justification.

## Testing

`cargo run --example testbed_2d` (press space a few times)

<img width="1280" alt="Screenshot 2025-03-10 at 1 02 03 PM"
src="https://github.com/user-attachments/assets/1e4ee39c-809b-4cc6-81bd-68e67b9625b5"
/>

---------

Co-authored-by: Ben Frankel <ben.frankel7@gmail.com>
2025-03-10 22:04:14 +00:00
François Mockers e57f73207e Smarter testbeds (#17573)
# Objective

- Improve CI when testing rendering by having smarter testbeds

## Solution

- CI testing no longer need a config file and will run with a default
config if not found
- It is now possible to give a name to a screenshot instead of just a
frame number
- 2d and 3d testbeds are now driven from code
  - a new system in testbed will watch for state changed
- on state changed, trigger a screenshot 100 frames after (so that the
scene has time to render) with the name of the scene
- when the screenshot is taken (`Captured` component has been removed),
switch scene
- this means less setup to run a testbed (no need for a config file),
screenshots have better names, and it's faster as we don't wait 100
frames for the screenshot to be taken

## Testing

- `cargo run --example testbed_2d --features bevy_ci_testing`
2025-01-31 22:38:39 +00:00
François Mockers fcfb685821 enable_state_scoped_entities() as a derive attribute (#16180)
# Objective

- I got tired of calling `enable_state_scoped_entities`, and though it
would make more sense to define that at the place where the state is
defined

## Solution

- add a derive attribute `#[states(scoped_entities)]` when derive
`States` or `SubStates` that enables it automatically when adding the
state

## Testing

- Ran the examples using it, they still work
2024-12-01 20:09:36 +00:00
François Mockers e1b9f545fb Introduce testbed examples starting with 2d (#15954)
# Objective

- Make progress for #15918 
- Start with 2d

## Solution

- Remove screenshots for existing examples as they're not deterministic
- Create new "testbed" example category, with a 2d one to start

## Testing

- Run `CI_TESTING_CONFIG=.github/example-run/testbed_2d.ron cargo run
--example testbed_2d --features "bevy_ci_testing"`
- ???
- Check the screenshots
2024-10-16 17:37:47 +00:00