Skip to content

Commit bf105ff

Browse files
committed
Add tests and document text2d aabb creation
1 parent fef0d9c commit bf105ff

File tree

2 files changed

+129
-4
lines changed

2 files changed

+129
-4
lines changed

crates/bevy_text/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,8 @@ glyph_brush_layout = "0.2.1"
3333
thiserror = "1.0"
3434
serde = { version = "1", features = ["derive"] }
3535

36+
[dev-dependencies]
37+
approx = "0.5.1"
38+
3639
[lints]
3740
workspace = true

crates/bevy_text/src/text2d.rs

Lines changed: 126 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,133 @@ pub fn calculate_bounds_text2d(
246246
>,
247247
) {
248248
for (entity, layout_info, anchor) in &text_to_update_aabb {
249+
// `Anchor::as_vec` gives us an offset relative to the text2d bounds, by negating it and scaling
250+
// by the logical size we compensate the transform offset in local space to get the center.
251+
let center = (-anchor.as_vec() * layout_info.logical_size)
252+
.extend(0.0)
253+
.into();
254+
// Distance in local space from the center to the x and y limits of the text2d bounds.
255+
let half_extents = (layout_info.logical_size / 2.0).extend(0.0).into();
249256
commands.entity(entity).try_insert(Aabb {
250-
center: (-anchor.as_vec() * layout_info.logical_size)
251-
.extend(0.0)
252-
.into(),
253-
half_extents: (layout_info.logical_size / 2.0).extend(0.0).into(),
257+
center,
258+
half_extents,
254259
});
255260
}
256261
}
262+
263+
#[cfg(test)]
264+
mod tests {
265+
266+
use bevy_app::{App, Update};
267+
use bevy_asset::{load_internal_binary_asset, Handle};
268+
use bevy_ecs::{event::Events, schedule::IntoSystemConfigs};
269+
use bevy_utils::default;
270+
271+
use super::*;
272+
273+
const FIRST_TEXT: &str = "Sample text.";
274+
const SECOND_TEXT: &str = "Another, longer sample text.";
275+
276+
fn setup() -> (App, Entity) {
277+
let mut app = App::new();
278+
app.init_resource::<Assets<Font>>()
279+
.init_resource::<Assets<Image>>()
280+
.init_resource::<Assets<TextureAtlasLayout>>()
281+
.init_resource::<TextSettings>()
282+
.init_resource::<FontAtlasWarning>()
283+
.init_resource::<FontAtlasSets>()
284+
.init_resource::<Events<WindowScaleFactorChanged>>()
285+
.insert_resource(TextPipeline::default())
286+
.add_systems(
287+
Update,
288+
(
289+
update_text2d_layout,
290+
calculate_bounds_text2d.after(update_text2d_layout),
291+
),
292+
);
293+
294+
// A font is needed to ensure the text is layed out with an actual size.
295+
load_internal_binary_asset!(
296+
app,
297+
Handle::default(),
298+
"FiraMono-subset.ttf",
299+
|bytes: &[u8], _path: String| { Font::try_from_bytes(bytes.to_vec()).unwrap() }
300+
);
301+
302+
let entity = app
303+
.world
304+
.spawn((Text2dBundle {
305+
text: Text::from_section(FIRST_TEXT, default()),
306+
..default()
307+
},))
308+
.id();
309+
310+
(app, entity)
311+
}
312+
313+
#[test]
314+
fn calculate_bounds_text2d_create_aabb() {
315+
let (mut app, entity) = setup();
316+
317+
assert!(!app
318+
.world
319+
.get_entity(entity)
320+
.expect("Could not find entity")
321+
.contains::<Aabb>());
322+
323+
// Creates the AABB after text layouting.
324+
app.update();
325+
326+
let aabb = app
327+
.world
328+
.get_entity(entity)
329+
.expect("Could not find entity")
330+
.get::<Aabb>()
331+
.expect("Text should have an AABB");
332+
333+
// Text2D AABB does not have a depth.
334+
assert_eq!(aabb.center.z, 0.0);
335+
assert_eq!(aabb.half_extents.z, 0.0);
336+
337+
// AABB has an actual size.
338+
assert!(aabb.half_extents.x > 0.0 && aabb.half_extents.y > 0.0);
339+
}
340+
341+
#[test]
342+
fn calculate_bounds_text2d_update_aabb() {
343+
let (mut app, entity) = setup();
344+
345+
// Creates the initial AABB after text layouting.
346+
app.update();
347+
348+
let first_aabb = *app
349+
.world
350+
.get_entity(entity)
351+
.expect("Could not find entity")
352+
.get::<Aabb>()
353+
.expect("Could not find initial AABB");
354+
355+
let mut entity_ref = app
356+
.world
357+
.get_entity_mut(entity)
358+
.expect("Could not find entity");
359+
*entity_ref
360+
.get_mut::<Text>()
361+
.expect("Missing Text on entity") = Text::from_section(SECOND_TEXT, default());
362+
363+
// Recomputes the AABB.
364+
app.update();
365+
366+
let second_aabb = *app
367+
.world
368+
.get_entity(entity)
369+
.expect("Could not find entity")
370+
.get::<Aabb>()
371+
.expect("Could not find second AABB");
372+
373+
// Check that the height is the same, but the width is greater.
374+
approx::assert_abs_diff_eq!(first_aabb.half_extents.y, second_aabb.half_extents.y);
375+
assert!(FIRST_TEXT.len() < SECOND_TEXT.len());
376+
assert!(first_aabb.half_extents.x < second_aabb.half_extents.x);
377+
}
378+
}

0 commit comments

Comments
 (0)