rafx_plugins/features/text/
plugin.rs

1use rafx::render_feature_renderer_prelude::*;
2
3use super::*;
4use crate::assets::font::FontAsset;
5use crate::phases::UiRenderPhase;
6use hydrate_base::handle::Handle;
7use rafx::assets::MaterialAsset;
8use rafx::renderer::RendererLoadContext;
9use std::path::PathBuf;
10
11pub struct TextStaticResources {
12    pub text_material: Handle<MaterialAsset>,
13    pub default_font: Handle<FontAsset>,
14}
15
16#[derive(Default)]
17pub struct TextRendererPlugin;
18
19#[cfg(feature = "legion")]
20impl TextRendererPlugin {
21    pub fn legion_init(
22        &self,
23        resources: &mut legion::Resources,
24    ) {
25        resources.insert(TextResource::new());
26    }
27
28    pub fn legion_destroy(resources: &mut legion::Resources) {
29        resources.remove::<TextResource>();
30    }
31}
32
33impl RenderFeaturePlugin for TextRendererPlugin {
34    fn add_asset_paths(
35        &self,
36        asset_paths: &mut Vec<PathBuf>,
37    ) {
38        asset_paths.push(PathBuf::from(concat!(
39            env!("CARGO_MANIFEST_DIR"),
40            "/assets"
41        )));
42    }
43
44    fn feature_debug_constants(&self) -> &'static RenderFeatureDebugConstants {
45        super::render_feature_debug_constants()
46    }
47
48    fn feature_index(&self) -> RenderFeatureIndex {
49        super::render_feature_index()
50    }
51
52    fn is_view_relevant(
53        &self,
54        view: &RenderView,
55    ) -> bool {
56        view.phase_is_relevant::<UiRenderPhase>()
57    }
58
59    fn requires_visible_render_objects(&self) -> bool {
60        false
61    }
62
63    fn configure_render_registry(
64        &self,
65        render_registry: RenderRegistryBuilder,
66    ) -> RenderRegistryBuilder {
67        render_registry.register_feature::<TextRenderFeature>()
68    }
69
70    fn initialize_static_resources(
71        &self,
72        renderer_load_context: &RendererLoadContext,
73        asset_manager: &mut AssetManager,
74        asset_resource: &mut AssetResource,
75        _extract_resources: &ExtractResources,
76        render_resources: &mut RenderResources,
77        _upload: &mut RafxTransferUpload,
78    ) -> RafxResult<()> {
79        let text_material = asset_resource
80            .load_artifact_symbol_name::<MaterialAsset>("rafx-plugins://materials/text.material");
81        let default_font = asset_resource
82            .load_artifact_symbol_name::<FontAsset>("rafx-plugins://fonts/mplus-1p-regular.ttf");
83
84        renderer_load_context.wait_for_asset_to_load(
85            render_resources,
86            asset_manager,
87            &text_material,
88            asset_resource,
89            "text material",
90        )?;
91
92        renderer_load_context.wait_for_asset_to_load(
93            render_resources,
94            asset_manager,
95            &default_font,
96            asset_resource,
97            "default font",
98        )?;
99
100        render_resources.insert(TextStaticResources {
101            text_material,
102            default_font,
103        });
104
105        render_resources.insert(FontAtlasCache::default());
106
107        Ok(())
108    }
109
110    fn new_frame_packet(
111        &self,
112        frame_packet_size: &FramePacketSize,
113    ) -> Box<dyn RenderFeatureFramePacket> {
114        Box::new(TextFramePacket::new(
115            self.feature_index(),
116            frame_packet_size,
117        ))
118    }
119
120    fn new_extract_job<'extract>(
121        &self,
122        extract_context: &RenderJobExtractContext<'extract>,
123        frame_packet: Box<dyn RenderFeatureFramePacket>,
124    ) -> Arc<dyn RenderFeatureExtractJob<'extract> + 'extract> {
125        let text_material = extract_context
126            .render_resources
127            .fetch::<TextStaticResources>()
128            .text_material
129            .clone();
130
131        TextExtractJob::new(extract_context, frame_packet.into_concrete(), text_material)
132    }
133
134    fn new_submit_packet(
135        &self,
136        frame_packet: &Box<dyn RenderFeatureFramePacket>,
137    ) -> Box<dyn RenderFeatureSubmitPacket> {
138        let frame_packet: &TextFramePacket = frame_packet.as_ref().as_concrete();
139        let num_submit_nodes = frame_packet.per_frame_data().get().text_draw_commands.len();
140
141        let mut view_submit_packets = Vec::with_capacity(frame_packet.view_packets().len());
142        for view_packet in frame_packet.view_packets() {
143            let view_submit_packet = ViewSubmitPacket::from_view_packet::<UiRenderPhase>(
144                view_packet,
145                Some(num_submit_nodes),
146            );
147            view_submit_packets.push(view_submit_packet);
148        }
149
150        Box::new(TextSubmitPacket::new(
151            self.feature_index(),
152            frame_packet.render_object_instances().len(),
153            view_submit_packets,
154        ))
155    }
156
157    fn new_prepare_job<'prepare>(
158        &self,
159        prepare_context: &RenderJobPrepareContext<'prepare>,
160        frame_packet: Box<dyn RenderFeatureFramePacket>,
161        submit_packet: Box<dyn RenderFeatureSubmitPacket>,
162    ) -> Arc<dyn RenderFeaturePrepareJob<'prepare> + 'prepare> {
163        TextPrepareJob::new(
164            prepare_context,
165            frame_packet.into_concrete(),
166            submit_packet.into_concrete(),
167        )
168    }
169
170    fn new_write_job<'write>(
171        &self,
172        write_context: &RenderJobWriteContext<'write>,
173        frame_packet: Box<dyn RenderFeatureFramePacket>,
174        submit_packet: Box<dyn RenderFeatureSubmitPacket>,
175    ) -> Arc<dyn RenderFeatureWriteJob<'write> + 'write> {
176        TextWriteJob::new(
177            write_context,
178            frame_packet.into_concrete(),
179            submit_packet.into_concrete(),
180        )
181    }
182}