Files
ickshonpe 133c8abe19 Stroke font text gizmos (#22732)
# Objective

Lightweight immediate mode stroke fonts text gizmo implementation.

Fixes #16490

## Solution

New `bevy_gizmos` module `text` containing functions `text` and
`text_2d` implemented for `GizmoBuffer`.

The `text` function has parameters:
- `isometry: Into<Isometry3d>`: defines the translation and rotation of
the text.
- `text: &str`: the text to be drawn.
- `size: f32`: the height of the glyphs.
- `anchor: Vec2`: anchor point relative to the center of the text.
- `color: Into<Color>`: the color of the text.

`text_2d` is the same, except the isometry is `Into<Isometry2d>`.

The glyph set is limited to ASCII characters from 33 to 126. 

The text rendering uses the Simplex Hershey font:
https://en.wikipedia.org/wiki/Hershey_fonts
https://paulbourke.net/dataformats/hershey/

The static font data is in the bevy_gizmos::text_font module.
Hershey fonts are public domain and don't require any attribution.

The text geometry isn't retained but since it's so simple, it's still
much faster than the retained Cosmic Text version I wrote initially.
That might not be the case if it's used to display whole pages of text,
but this isn't intended for that.

Glyphs are drawn using linestrips.

### Limitations

* I think this would be better with a monospaced font but it's using a
proportional font atm.

* Only supports left-to-right, left justified text.

* Line height is fixed.

* Can't set the color of individual glyphs.

* Can't change the font.

## Testing

Example displaying text gizmos rotating in 3d
```
cargo run --example 3d_text_gizmos
```

Example displaying all the glyphs from the text gizmos font:
```
cargo run --example text_gizmos_font
```

Larger example with lots of text and an FPS counter:
```
cargo run --example 2d_text_gizmos
```

Example demonstrating anchors:
```
cargo run --example anchored_text_gizmos
```

## Showcase


<img width="1861" height="872" alt="tg-example"
src="https://github.com/user-attachments/assets/d54802cb-23fa-46fc-a20f-3ab004e57f8a"
/>

<img width="792" height="676" alt="anchors"
src="https://github.com/user-attachments/assets/29a8b3b0-516f-4bbc-885e-f8b23db01f88"
/>

<img width="1325" height="405" alt="hello_text_gizmos"
src="https://github.com/user-attachments/assets/b07dc5fb-4be4-4777-b5fd-219c54333328"
/>

<img width="1924" height="1127" alt="all_glyphs"
src="https://github.com/user-attachments/assets/92f7bebd-641c-43a7-9c0a-a56bbb828b5e"
/>

<img width="661" height="738" alt="text-gizmos-3d"
src="https://github.com/user-attachments/assets/91c9caaa-ca13-4a94-9c60-ec326ddeae8a"
/>

<img width="1977" height="1185" alt="2d_gizmos"
src="https://github.com/user-attachments/assets/5f1ae276-795a-4eac-ae2e-3faf7348be2c"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2026-02-07 19:52:07 +00:00

52 lines
1.3 KiB
Rust

//! Basic example demonstrating 3d text gizmos
use bevy::color::palettes::css::{ORANGE, RED, YELLOW};
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup_camera)
.add_systems(Update, hello_world)
.run();
}
fn setup_camera(mut commands: Commands, mut gizmo_config_store: ResMut<GizmoConfigStore>) {
commands.spawn((
Camera3d::default(),
Transform::from_xyz(0.0, 0.0, 10.0).looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
));
let (config, _) = gizmo_config_store.config_mut::<DefaultGizmoConfigGroup>();
config.line.width = 4.;
}
fn hello_world(mut text_gizmos: Gizmos, time: Res<Time>) {
let t = 0.2 * time.elapsed_secs();
text_gizmos.text(
Isometry3d::new(Vec3::new(0.0, 1.5, 0.0), Quat::from_rotation_y(-t)),
"Hello",
1.,
Vec2::ZERO,
RED,
);
text_gizmos.text(
Isometry3d::new(Vec3::new(0.0, 0.0, 0.0), Quat::from_rotation_y(t + 0.25)),
"Text",
1.,
Vec2::ZERO,
ORANGE,
);
text_gizmos.text(
Isometry3d::new(Vec3::new(0.0, -1.5, 0.0), Quat::from_rotation_y(-t - 0.5)),
"Gizmos",
1.,
Vec2::ZERO,
YELLOW,
);
}