@@ -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