bevy_immediate/ui/
text.rs

1use std::ops::Deref;
2
3use bevy_ui::widget::Text;
4
5use crate::{CapSet, ImmCapability, ImmEntity, ImplCap};
6
7/// Capability that makes [`bevy_ui::Interaction`] accessible from immediate UI
8pub struct CapabilityUiText;
9
10impl ImmCapability for CapabilityUiText {
11    fn build<Cap: CapSet>(app: &mut bevy_app::App, cap_req: &mut crate::ImmCapAccessRequests<Cap>) {
12        cap_req.request_component_write::<Text>(app.world_mut());
13    }
14}
15
16/// Implements methods to access [`bevy_ui::Interaction`] in immediate mode
17pub trait ImmUiText {
18    /// Insert [`Text`] on entity spawn and update it to given text upon change
19    fn text(self, text: impl Deref<Target = str> + Into<String>) -> Self;
20
21    /// On entity spawn insert given text into [`Text`]
22    fn on_spawn_text_fn(self, text: impl FnOnce() -> String) -> Self;
23
24    /// On entity spawn insert given text into [`Text`]
25    fn on_spawn_text(self, text: &str) -> Self;
26
27    /// Insert text if something changed
28    fn on_change_text_fn(self, changed: bool, text: impl FnOnce() -> String) -> Self;
29}
30
31impl<Cap> ImmUiText for ImmEntity<'_, '_, '_, Cap>
32where
33    Cap: ImplCap<CapabilityUiText>,
34{
35    fn text(mut self, text: impl Deref<Target = str> + Into<String>) -> Self {
36        'text_exists: {
37            let Ok(Some(mut text_comp)) = self.cap_get_component_mut::<Text>() else {
38                break 'text_exists;
39            };
40
41            // No need to update text and trigger state change
42            if text_comp.0 == text.deref() {
43                return self;
44            }
45            *text_comp = Text(text.into());
46
47            return self;
48        }
49
50        // Fallback
51        self.entity_commands().insert_if_new(Text(text.into()));
52        self
53    }
54
55    fn on_spawn_text_fn(self, text: impl FnOnce() -> String) -> Self {
56        self.on_spawn_insert(|| Text(text()))
57    }
58
59    fn on_spawn_text(self, text: &str) -> Self {
60        self.on_spawn_insert(|| Text(text.to_owned()))
61    }
62
63    fn on_change_text_fn(self, changed: bool, text: impl FnOnce() -> String) -> Self {
64        self.on_change_insert(changed, || Text(text()))
65    }
66}