@@ -6,7 +6,7 @@ use bevy_camera::visibility::ViewVisibility;
66use bevy_color:: LinearRgba ;
77use bevy_ecs:: {
88 entity:: Entity ,
9- query:: With ,
9+ query:: Has ,
1010 system:: { Commands , Query , Res , ResMut } ,
1111} ;
1212use bevy_image:: prelude:: * ;
@@ -16,7 +16,7 @@ use bevy_render::Extract;
1616use bevy_sprite:: { Anchor , Text2dShadow } ;
1717use bevy_text:: {
1818 ComputedTextBlock , PositionedGlyph , Strikethrough , TextBackgroundColor , TextBounds , TextColor ,
19- TextLayoutInfo ,
19+ TextLayoutInfo , Underline ,
2020} ;
2121use bevy_transform:: prelude:: GlobalTransform ;
2222
@@ -41,7 +41,7 @@ pub fn extract_text2d_sprite(
4141 > ,
4242 text_colors : Extract < Query < & TextColor > > ,
4343 text_background_colors_query : Extract < Query < & TextBackgroundColor > > ,
44- strikethrough_query : Extract < Query < & TextColor , With < Strikethrough > > > ,
44+ decoration_query : Extract < Query < ( & TextColor , Has < Strikethrough > , Has < Underline > ) > > ,
4545) {
4646 let mut start = extracted_slices. slices . len ( ) ;
4747 let mut end = start + 1 ;
@@ -71,7 +71,7 @@ pub fn extract_text2d_sprite(
7171
7272 let top_left = ( Anchor :: TOP_LEFT . 0 - anchor. as_vec ( ) ) * size;
7373
74- for & ( section_index, rect, _, _) in text_layout_info. section_geometry . iter ( ) {
74+ for & ( section_index, rect, _, _, _ ) in text_layout_info. section_geometry . iter ( ) {
7575 let section_entity = computed_block. entities ( ) [ section_index] . entity ;
7676 let Ok ( text_background_color) = text_background_colors_query. get ( section_entity) else {
7777 continue ;
@@ -149,32 +149,59 @@ pub fn extract_text2d_sprite(
149149 end += 1 ;
150150 }
151151
152- for & ( section_index, rect, strikethrough_y, stroke) in
152+ for & ( section_index, rect, strikethrough_y, stroke, underline_y ) in
153153 text_layout_info. section_geometry . iter ( )
154154 {
155155 let section_entity = computed_block. entities ( ) [ section_index] . entity ;
156- let Ok ( _) = strikethrough_query. get ( section_entity) else {
156+ let Ok ( ( _, has_strikethrough, has_underline) ) =
157+ decoration_query. get ( section_entity)
158+ else {
157159 continue ;
158160 } ;
159- let render_entity = commands. spawn ( TemporaryRenderEntity ) . id ( ) ;
160- let offset = Vec2 :: new ( rect. center ( ) . x , -strikethrough_y - 0.5 * stroke) ;
161- let transform =
162- shadow_transform * GlobalTransform :: from_translation ( offset. extend ( 0. ) ) ;
163- extracted_sprites. sprites . push ( ExtractedSprite {
164- main_entity,
165- render_entity,
166- transform,
167- color,
168- image_handle_id : AssetId :: default ( ) ,
169- flip_x : false ,
170- flip_y : false ,
171- kind : ExtractedSpriteKind :: Single {
172- anchor : Vec2 :: ZERO ,
173- rect : None ,
174- scaling_mode : None ,
175- custom_size : Some ( Vec2 :: new ( rect. size ( ) . x , stroke) ) ,
176- } ,
177- } ) ;
161+
162+ if has_strikethrough {
163+ let render_entity = commands. spawn ( TemporaryRenderEntity ) . id ( ) ;
164+ let offset = Vec2 :: new ( rect. center ( ) . x , -strikethrough_y - 0.5 * stroke) ;
165+ let transform =
166+ shadow_transform * GlobalTransform :: from_translation ( offset. extend ( 0. ) ) ;
167+ extracted_sprites. sprites . push ( ExtractedSprite {
168+ main_entity,
169+ render_entity,
170+ transform,
171+ color,
172+ image_handle_id : AssetId :: default ( ) ,
173+ flip_x : false ,
174+ flip_y : false ,
175+ kind : ExtractedSpriteKind :: Single {
176+ anchor : Vec2 :: ZERO ,
177+ rect : None ,
178+ scaling_mode : None ,
179+ custom_size : Some ( Vec2 :: new ( rect. size ( ) . x , stroke) ) ,
180+ } ,
181+ } ) ;
182+ }
183+
184+ if has_underline {
185+ let render_entity = commands. spawn ( TemporaryRenderEntity ) . id ( ) ;
186+ let offset = Vec2 :: new ( rect. center ( ) . x , -underline_y - 0.5 * stroke) ;
187+ let transform =
188+ shadow_transform * GlobalTransform :: from_translation ( offset. extend ( 0. ) ) ;
189+ extracted_sprites. sprites . push ( ExtractedSprite {
190+ main_entity,
191+ render_entity,
192+ transform,
193+ color,
194+ image_handle_id : AssetId :: default ( ) ,
195+ flip_x : false ,
196+ flip_y : false ,
197+ kind : ExtractedSpriteKind :: Single {
198+ anchor : Vec2 :: ZERO ,
199+ rect : None ,
200+ scaling_mode : None ,
201+ custom_size : Some ( Vec2 :: new ( rect. size ( ) . x , stroke) ) ,
202+ } ,
203+ } ) ;
204+ }
178205 }
179206 }
180207
@@ -239,34 +266,62 @@ pub fn extract_text2d_sprite(
239266 end += 1 ;
240267 }
241268
242- for & ( section_index, rect, strikethrough_y, stroke) in
269+ for & ( section_index, rect, strikethrough_y, stroke, underline_y ) in
243270 text_layout_info. section_geometry . iter ( )
244271 {
245272 let section_entity = computed_block. entities ( ) [ section_index] . entity ;
246- let Ok ( text_color) = strikethrough_query. get ( section_entity) else {
273+ let Ok ( ( text_color, has_strike_through, has_underline) ) =
274+ decoration_query. get ( section_entity)
275+ else {
247276 continue ;
248277 } ;
249- let render_entity = commands. spawn ( TemporaryRenderEntity ) . id ( ) ;
250- let offset = Vec2 :: new ( rect. center ( ) . x , -strikethrough_y - 0.5 * stroke) ;
251- let transform = * global_transform
252- * GlobalTransform :: from_translation ( top_left. extend ( 0. ) )
253- * scaling
254- * GlobalTransform :: from_translation ( offset. extend ( 0. ) ) ;
255- extracted_sprites. sprites . push ( ExtractedSprite {
256- main_entity,
257- render_entity,
258- transform,
259- color : text_color. 0 . into ( ) ,
260- image_handle_id : AssetId :: default ( ) ,
261- flip_x : false ,
262- flip_y : false ,
263- kind : ExtractedSpriteKind :: Single {
264- anchor : Vec2 :: ZERO ,
265- rect : None ,
266- scaling_mode : None ,
267- custom_size : Some ( Vec2 :: new ( rect. size ( ) . x , stroke) ) ,
268- } ,
269- } ) ;
278+ if has_strike_through {
279+ let render_entity = commands. spawn ( TemporaryRenderEntity ) . id ( ) ;
280+ let offset = Vec2 :: new ( rect. center ( ) . x , -strikethrough_y - 0.5 * stroke) ;
281+ let transform = * global_transform
282+ * GlobalTransform :: from_translation ( top_left. extend ( 0. ) )
283+ * scaling
284+ * GlobalTransform :: from_translation ( offset. extend ( 0. ) ) ;
285+ extracted_sprites. sprites . push ( ExtractedSprite {
286+ main_entity,
287+ render_entity,
288+ transform,
289+ color : text_color. 0 . into ( ) ,
290+ image_handle_id : AssetId :: default ( ) ,
291+ flip_x : false ,
292+ flip_y : false ,
293+ kind : ExtractedSpriteKind :: Single {
294+ anchor : Vec2 :: ZERO ,
295+ rect : None ,
296+ scaling_mode : None ,
297+ custom_size : Some ( Vec2 :: new ( rect. size ( ) . x , stroke) ) ,
298+ } ,
299+ } ) ;
300+ }
301+
302+ if has_underline {
303+ let render_entity = commands. spawn ( TemporaryRenderEntity ) . id ( ) ;
304+ let offset = Vec2 :: new ( rect. center ( ) . x , -underline_y - 0.5 * stroke) ;
305+ let transform = * global_transform
306+ * GlobalTransform :: from_translation ( top_left. extend ( 0. ) )
307+ * scaling
308+ * GlobalTransform :: from_translation ( offset. extend ( 0. ) ) ;
309+ extracted_sprites. sprites . push ( ExtractedSprite {
310+ main_entity,
311+ render_entity,
312+ transform,
313+ color : text_color. 0 . into ( ) ,
314+ image_handle_id : AssetId :: default ( ) ,
315+ flip_x : false ,
316+ flip_y : false ,
317+ kind : ExtractedSpriteKind :: Single {
318+ anchor : Vec2 :: ZERO ,
319+ rect : None ,
320+ scaling_mode : None ,
321+ custom_size : Some ( Vec2 :: new ( rect. size ( ) . x , stroke) ) ,
322+ } ,
323+ } ) ;
324+ }
270325 }
271326 }
272327}
0 commit comments