pub(crate) fn process_text_system(
    mut text_pipeline: ResMut<DefaultTextPipeline>,
    text_nodes: Query<(
        Entity,
        &Node,
        (&UiText, ChangeTrackers<UiText>),
        Option<(&TextSize, ChangeTrackers<TextSize>)>,
        Option<(&Handle<Font>, ChangeTrackers<Handle<Font>>)>,
        Option<(&TextDetails, ChangeTrackers<TextDetails>)>,
        Option<(&TextAlign, ChangeTrackers<TextAlign>)>,
    )>,
    fonts: Res<Assets<Font>>,

    mut last_scale_factor: Local<f64>,

    mut textures: ResMut<Assets<Image>>,
    mut texture_atlases: ResMut<Assets<TextureAtlas>>,
    mut font_atlas_set_storage: ResMut<Assets<FontAtlasSet>>,

    windows: Res<Windows>,
) {
    let scale_factor = windows
        .get_primary()
        .map(|w| w.scale_factor())
        .unwrap_or(1.);

    fn check_tuple<T: Component>(x: &Option<(&T, ChangeTrackers<T>)>) -> bool {
        x.as_ref().map(|(_, x)| !x.is_changed()).unwrap_or(true)
    }

    for (entity, node, text, size, font, details, align) in text_nodes.iter() {
        if *last_scale_factor == scale_factor
            && !text.1.is_changed()
            && check_tuple(&size)
            && check_tuple(&font)
            && check_tuple(&details)
            && check_tuple(&align)
        {
            continue;
        }

        let text_details = details.map(|x| &*x.0 .0).unwrap_or(&[]);
        let mut style = None;
        let mut start = 0;

        let sections = text_details
            .iter()
            .map(|(style, ends_at)| (style, *ends_at))
            .chain(std::iter::once_with(|| {
                style = Some(TextStyle {
                    font: font
                        .map(|f| f.0.clone_weak())
                        .unwrap_or_else(|| DEFAULT_FONT.typed()),
                    font_size: size.map(|s| s.0 .0).unwrap_or(14.),
                    color: Color::WHITE, // color not relevant to layout
                });
                (style.as_ref().unwrap(), text.0 .0.as_bytes().len())
            }))
            .map(|(style, end)| {
                let r = TextSection {
                    value: text.0 .0[start..end].to_owned(),
                    style: style.clone(),
                };
                start = end;
                r
            })
            .collect::<Vec<_>>();

        text_pipeline
            .queue_text(
                entity,
                &fonts,
                &sections,
                scale_factor,
                align.map(|(a, _)| a.0).unwrap_or_default(),
                bevy::math::Size::new(node.size.x, node.size.y),
                &mut font_atlas_set_storage,
                &mut texture_atlases,
                &mut textures,
            )
            .ok();

        *last_scale_factor = scale_factor;
    }
}
// todo: replace with layout-driven method when morphorm supports it
replace with layout-driven method when morphorm supports it
replace with layout - driven method when morphorm supports it
pub(crate) fn process_text_system(
    mut text_pipeline: ResMut<DefaultTextPipeline>,
    text_nodes: Query<(
        Entity,
        &Node,
        (&UiText, ChangeTrackers<UiText>),
        Option<(&TextSize, ChangeTrackers<TextSize>)>,
        Option<(&Handle<Font>, ChangeTrackers<Handle<Font>>)>,
        Option<(&TextDetails, ChangeTrackers<TextDetails>)>,
        Option<(&TextAlign, ChangeTrackers<TextAlign>)>,
    )>,
    fonts: Res<Assets<Font>>,
    mut last_scale_factor: Local<f64>,
    mut textures: ResMut<Assets<Image>>,
    mut texture_atlases: ResMut<Assets<TextureAtlas>>,
    mut font_atlas_set_storage: ResMut<Assets<FontAtlasSet>>,
    windows: Res<Windows>,
) {
    let scale_factor = windows
        .get_primary()
        .map(|w| w.scale_factor())
        .unwrap_or(1.);
    fn check_tuple<T: Component>(x: &Option<(&T, ChangeTrackers<T>)>) -> bool {
        x.as_ref().map(|(_, x)| !x.is_changed()).unwrap_or(true)
    }
    for (entity, node, text, size, font, details, align) in text_nodes.iter() {
        if *last_scale_factor == scale_factor
            && !text.1.is_changed()
            && check_tuple(&size)
            && check_tuple(&font)
            && check_tuple(&details)
            && check_tuple(&align)
        {
            continue;
        }
        let text_details = details.map(|x| &*x.0 .0).unwrap_or(&[]);
        let mut style = None;
        let mut start = 0;
        let sections = text_details
            .iter()
            .map(|(style, ends_at)| (style, *ends_at))
            .chain(std::iter::once_with(|| {
                style = Some(TextStyle {
                    font: font
                        .map(|f| f.0.clone_weak())
                        .unwrap_or_else(|| DEFAULT_FONT.typed()),
                    font_size: size.map(|s| s.0 .0).unwrap_or(14.),
                    color: Color::WHITE, // color not relevant to layout
                });
                (style.as_ref().unwrap(), text.0 .0.as_bytes().len())
            }))
            .map(|(style, end)| {
                let r = TextSection {
                    value: text.0 .0[start..end].to_owned(),
                    style: style.clone(),
                };
                start = end;
                r
            })
            .collect::<Vec<_>>();
        text_pipeline
            .queue_text(
                entity,
                &fonts,
                &sections,
                scale_factor,
                align.map(|(a, _)| a.0).unwrap_or_default(),
                bevy::math::Size::new(node.size.x, node.size.y),
                &mut font_atlas_set_storage,
                &mut texture_atlases,
                &mut textures,
            )
            .ok();
        *last_scale_factor = scale_factor;
    }
}
pub ( crate ) fn process_text_system ( mut text_pipeline : ResMut < DefaultTextPipeline > , text_nodes : Query < ( Entity , & Node , ( & UiText , ChangeTrackers < UiText > ) , Option < ( & TextSize , ChangeTrackers < TextSize > ) > , Option < ( & Handle < Font > , ChangeTrackers < Handle < Font > > ) > , Option < ( & TextDetails , ChangeTrackers < TextDetails > ) > , Option < ( & TextAlign , ChangeTrackers < TextAlign > ) > , ) > , fonts : Res < Assets < Font > > , mut last_scale_factor : Local < f64 > , mut textures : ResMut < Assets < Image > > , mut texture_atlases : ResMut < Assets < TextureAtlas > > , mut font_atlas_set_storage : ResMut < Assets < FontAtlasSet > > , windows : Res < Windows > , ) { let scale_factor = windows . get_primary ( ) . map ( | w | w . scale_factor ( ) ) . unwrap_or ( 1. ) ; fn check_tuple < T : Component > ( x : & Option < ( & T , ChangeTrackers < T > ) > ) -> bool { x . as_ref ( ) . map ( | ( _ , x ) | ! x . is_changed ( ) ) . unwrap_or ( true ) } for ( entity , node , text , size , font , details , align ) in text_nodes . iter ( ) { if * last_scale_factor == scale_factor && ! text . 1 . is_changed ( ) && check_tuple ( & size ) && check_tuple ( & font ) && check_tuple ( & details ) && check_tuple ( & align ) { continue ; } let text_details = details . map ( | x | & * x . 0 . 0 ) . unwrap_or ( & [ ] ) ; let mut style = None ; let mut start = 0 ; let sections = text_details . iter ( ) . map ( | ( style , ends_at ) | ( style , * ends_at ) ) . chain ( std :: iter :: once_with ( | | { style = Some ( TextStyle { font : font . map ( | f | f . 0 . clone_weak ( ) ) . unwrap_or_else ( | | DEFAULT_FONT . typed ( ) ) , font_size : size . map ( | s | s . 0 . 0 ) . unwrap_or ( 14. ) , color : Color :: WHITE , // color not relevant to layout } ) ; ( style . as_ref ( ) . unwrap ( ) , text . 0 . 0 . as_bytes ( ) . len ( ) ) } ) ) . map ( | ( style , end ) | { let r = TextSection { value : text . 0 . 0 [ start .. end ] . to_owned ( ) , style : style . clone ( ) , } ; start = end ; r } ) . collect :: < Vec < _ > > ( ) ; text_pipeline . queue_text ( entity , & fonts , & sections , scale_factor , align . map ( | ( a , _ ) | a . 0 ) . unwrap_or_default ( ) , bevy :: math :: Size :: new ( node . size . x , node . size . y ) , & mut font_atlas_set_storage , & mut texture_atlases , & mut textures , ) . ok ( ) ; * last_scale_factor = scale_factor ; } }
todo: replace with layout-driven method when morphorm supports it
todo : replace with layout - driven method when morphorm supports it
text_pipeline
ResMut<DefaultTextPipeline>
text_nodes
Query<(
        Entity,
        &Node,
        (&UiText, ChangeTrackers<UiText>),
        Option<(&TextSize, ChangeTrackers<TextSize>)>,
        Option<(&Handle<Font>, ChangeTrackers<Handle<Font>>)>,
        Option<(&TextDetails, ChangeTrackers<TextDetails>)>,
        Option<(&TextAlign, ChangeTrackers<TextAlign>)>,
    )>
fonts
Res<Assets<Font>>
last_scale_factor
Local<f64>
textures
ResMut<Assets<Image>>
texture_atlases
ResMut<Assets<TextureAtlas>>
font_atlas_set_storage
ResMut<Assets<FontAtlasSet>>
windows
Res<Windows>
text_pipeline
ResMut<DefaultTextPipeline>
text_nodes
Query<(
        Entity,
        &Node,
        (&UiText, ChangeTrackers<UiText>),
        Option<(&TextSize, ChangeTrackers<TextSize>)>,
        Option<(&Handle<Font>, ChangeTrackers<Handle<Font>>)>,
        Option<(&TextDetails, ChangeTrackers<TextDetails>)>,
        Option<(&TextAlign, ChangeTrackers<TextAlign>)>,
    )>
fonts
Res<Assets<Font>>
last_scale_factor
Local<f64>
textures
ResMut<Assets<Image>>
texture_atlases
ResMut<Assets<TextureAtlas>>
font_atlas_set_storage
ResMut<Assets<FontAtlasSet>>
windows
Res<Windows>