hephae_text/
lib.rs

1#![allow(internal_features)]
2#![cfg_attr(any(docsrs, docsrs_dep), feature(rustdoc_internals))]
3#![doc = include_str!("../README.md")]
4#![cfg_attr(doc, deny(missing_docs))]
5
6use std::sync::Mutex;
7
8use bevy_app::{PluginGroupBuilder, prelude::*};
9use bevy_asset::prelude::*;
10use bevy_ecs::prelude::*;
11use bevy_render::{RenderApp, prelude::*};
12pub use cosmic_text;
13use hephae_utils::prelude::*;
14
15use crate::{
16    atlas::{ExtractedFontAtlases, FontAtlas, extract_font_atlases},
17    def::{Font, FontLoader, Text, TextAlign, TextFont, TextSpan, TextWrap, compute_structure, notify_structure},
18    layout::{FontLayout, FontLayoutInner, load_fonts_to_database},
19};
20
21pub mod atlas;
22pub mod def;
23pub mod layout;
24
25/// Common imports for [`hephae_text`](crate).
26pub mod prelude {
27    pub use crate::{
28        atlas::ExtractedFontAtlases,
29        def::{Font, Text, TextAlign, TextFont, TextGlyph, TextGlyphs, TextSpan, TextStructure, TextWrap},
30        layout::FontLayout,
31    };
32}
33
34plugin_def! {
35    /// Provides text-rendering functionality into the app.
36    #[plugin_group]
37    pub struct TextPlugin;
38    fn build(self) -> PluginGroupBuilder {
39        #[allow(unused_mut)]
40        let mut builder = PluginGroupBuilder::start::<Self>().add(|app: &mut App| {
41            let (sender, receiver) = async_channel::bounded(4);
42            app.init_asset::<Font>()
43                .init_asset::<FontAtlas>()
44                .register_asset_loader(FontLoader { add_to_database: sender })
45                .insert_resource(FontLayout(Mutex::new(FontLayoutInner::new(receiver))))
46                .register_type::<Text>()
47                .register_type::<TextWrap>()
48                .register_type::<TextAlign>()
49                .register_type::<TextFont>()
50                .register_type::<TextSpan>()
51                .configure_sets(Update, HephaeTextSystems::LoadFontsToDatabase)
52                .configure_sets(PostUpdate, HephaeTextSystems::ComputeStructure)
53                .add_systems(Update, load_fonts_to_database.in_set(HephaeTextSystems::LoadFontsToDatabase))
54                .add_systems(
55                    PostUpdate,
56                    (compute_structure, notify_structure)
57                        .chain()
58                        .in_set(HephaeTextSystems::ComputeStructure),
59                );
60
61            if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
62                render_app
63                    .init_resource::<ExtractedFontAtlases>()
64                    .configure_sets(ExtractSchedule, HephaeTextSystems::ExtractFontAtlases)
65                    .add_systems(
66                        ExtractSchedule,
67                        extract_font_atlases.in_set(HephaeTextSystems::ExtractFontAtlases),
68                    );
69            }
70        });
71
72        #[cfg(feature = "locale")]
73        {
74            builder = builder
75                .add(hephae_locale::LocaleTargetPlugin::<Text>::default())
76                .add(hephae_locale::LocaleTargetPlugin::<TextSpan>::default());
77        }
78
79        builder
80    }
81}
82
83/// Labels for systems added by Hephae Text.
84#[derive(SystemSet, Debug, Copy, Clone, PartialEq, Eq, Hash)]
85pub enum HephaeTextSystems {
86    /// System in [`ExtractSchedule`] that extracts font atlases into the render world.
87    ExtractFontAtlases,
88    /// System in [`Update`] that loads bytes sent from [`FontLoader`] into a [`Font`] and adds them
89    /// to the database.
90    LoadFontsToDatabase,
91    /// System in [`PostUpdate`] that computes and marks [`TextStructure`](def::TextStructure) as
92    /// changed as necessary, for convenience of systems wishing to listen for change-detection.
93    ComputeStructure,
94}