ui: remove translation/rotation/scale components (Node serves the same role)
This commit is contained in:
		
							parent
							
								
									726eb37198
								
							
						
					
					
						commit
						9a236f4923
					
				@ -17,7 +17,7 @@
 | 
				
			|||||||
use core::{
 | 
					use core::{
 | 
				
			||||||
    ops::{Deref, DerefMut},
 | 
					    ops::{Deref, DerefMut},
 | 
				
			||||||
    ptr::NonNull,
 | 
					    ptr::NonNull,
 | 
				
			||||||
    sync::atomic::{AtomicUsize, Ordering},
 | 
					    sync::atomic::{AtomicUsize, Ordering}, fmt::Debug,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{archetype::Archetype, Component, MissingComponent};
 | 
					use crate::{archetype::Archetype, Component, MissingComponent};
 | 
				
			||||||
@ -101,6 +101,12 @@ impl<'a, T: Component> Deref for Ref<'a, T> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a, T: Component> Debug for Ref<'a,T> where T: Debug {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | 
				
			||||||
 | 
					        self.deref().fmt(f)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Unique borrow of an entity's component
 | 
					/// Unique borrow of an entity's component
 | 
				
			||||||
pub struct RefMut<'a, T: Component> {
 | 
					pub struct RefMut<'a, T: Component> {
 | 
				
			||||||
    archetype: &'a Archetype,
 | 
					    archetype: &'a Archetype,
 | 
				
			||||||
@ -155,6 +161,12 @@ impl<'a, T: Component> DerefMut for RefMut<'a, T> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a, T: Component> Debug for RefMut<'a,T> where T: Debug {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | 
				
			||||||
 | 
					        self.deref().fmt(f)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Handle to an entity with any component types
 | 
					/// Handle to an entity with any component types
 | 
				
			||||||
#[derive(Copy, Clone)]
 | 
					#[derive(Copy, Clone)]
 | 
				
			||||||
pub struct EntityRef<'a> {
 | 
					pub struct EntityRef<'a> {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
use super::Node;
 | 
					use super::Node;
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    render::UI_PIPELINE_HANDLE,
 | 
					    render::UI_PIPELINE_HANDLE,
 | 
				
			||||||
    widget::{Button, Label},
 | 
					    widget::{Button, Text},
 | 
				
			||||||
    Click, Hover, FocusPolicy,
 | 
					    Click, FocusPolicy, Hover,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use bevy_asset::Handle;
 | 
					use bevy_asset::Handle;
 | 
				
			||||||
use bevy_ecs::Bundle;
 | 
					use bevy_ecs::Bundle;
 | 
				
			||||||
@ -12,7 +12,7 @@ use bevy_render::{
 | 
				
			|||||||
    pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
 | 
					    pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use bevy_sprite::{ColorMaterial, QUAD_HANDLE};
 | 
					use bevy_sprite::{ColorMaterial, QUAD_HANDLE};
 | 
				
			||||||
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
 | 
					use bevy_transform::{components::LocalTransform, prelude::Transform};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Bundle)]
 | 
					#[derive(Bundle)]
 | 
				
			||||||
pub struct NodeComponents {
 | 
					pub struct NodeComponents {
 | 
				
			||||||
@ -22,9 +22,7 @@ pub struct NodeComponents {
 | 
				
			|||||||
    pub draw: Draw,
 | 
					    pub draw: Draw,
 | 
				
			||||||
    pub render_pipelines: RenderPipelines,
 | 
					    pub render_pipelines: RenderPipelines,
 | 
				
			||||||
    pub transform: Transform,
 | 
					    pub transform: Transform,
 | 
				
			||||||
    pub translation: Translation,
 | 
					    pub local_transform: LocalTransform,
 | 
				
			||||||
    pub rotation: Rotation,
 | 
					 | 
				
			||||||
    pub scale: Scale,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for NodeComponents {
 | 
					impl Default for NodeComponents {
 | 
				
			||||||
@ -53,29 +51,25 @@ impl Default for NodeComponents {
 | 
				
			|||||||
            material: Default::default(),
 | 
					            material: Default::default(),
 | 
				
			||||||
            draw: Default::default(),
 | 
					            draw: Default::default(),
 | 
				
			||||||
            transform: Default::default(),
 | 
					            transform: Default::default(),
 | 
				
			||||||
            translation: Default::default(),
 | 
					            local_transform: Default::default(),
 | 
				
			||||||
            rotation: Default::default(),
 | 
					 | 
				
			||||||
            scale: Default::default(),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Bundle)]
 | 
					#[derive(Bundle)]
 | 
				
			||||||
pub struct LabelComponents {
 | 
					pub struct TextComponents {
 | 
				
			||||||
    pub node: Node,
 | 
					    pub node: Node,
 | 
				
			||||||
    pub draw: Draw,
 | 
					    pub draw: Draw,
 | 
				
			||||||
    pub label: Label,
 | 
					    pub text: Text,
 | 
				
			||||||
    pub focus_policy: FocusPolicy,
 | 
					    pub focus_policy: FocusPolicy,
 | 
				
			||||||
    pub transform: Transform,
 | 
					    pub transform: Transform,
 | 
				
			||||||
    pub translation: Translation,
 | 
					    pub local_transform: LocalTransform,
 | 
				
			||||||
    pub rotation: Rotation,
 | 
					 | 
				
			||||||
    pub scale: Scale,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for LabelComponents {
 | 
					impl Default for TextComponents {
 | 
				
			||||||
    fn default() -> Self {
 | 
					    fn default() -> Self {
 | 
				
			||||||
        LabelComponents {
 | 
					        TextComponents {
 | 
				
			||||||
            label: Label::default(),
 | 
					            text: Text::default(),
 | 
				
			||||||
            node: Default::default(),
 | 
					            node: Default::default(),
 | 
				
			||||||
            focus_policy: FocusPolicy::Pass,
 | 
					            focus_policy: FocusPolicy::Pass,
 | 
				
			||||||
            draw: Draw {
 | 
					            draw: Draw {
 | 
				
			||||||
@ -83,9 +77,7 @@ impl Default for LabelComponents {
 | 
				
			|||||||
                ..Default::default()
 | 
					                ..Default::default()
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            transform: Default::default(),
 | 
					            transform: Default::default(),
 | 
				
			||||||
            translation: Default::default(),
 | 
					            local_transform: Default::default(),
 | 
				
			||||||
            rotation: Default::default(),
 | 
					 | 
				
			||||||
            scale: Default::default(),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -102,9 +94,7 @@ pub struct ButtonComponents {
 | 
				
			|||||||
    pub draw: Draw,
 | 
					    pub draw: Draw,
 | 
				
			||||||
    pub render_pipelines: RenderPipelines,
 | 
					    pub render_pipelines: RenderPipelines,
 | 
				
			||||||
    pub transform: Transform,
 | 
					    pub transform: Transform,
 | 
				
			||||||
    pub translation: Translation,
 | 
					    pub local_transform: LocalTransform,
 | 
				
			||||||
    pub rotation: Rotation,
 | 
					 | 
				
			||||||
    pub scale: Scale,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for ButtonComponents {
 | 
					impl Default for ButtonComponents {
 | 
				
			||||||
@ -137,9 +127,7 @@ impl Default for ButtonComponents {
 | 
				
			|||||||
            material: Default::default(),
 | 
					            material: Default::default(),
 | 
				
			||||||
            draw: Default::default(),
 | 
					            draw: Default::default(),
 | 
				
			||||||
            transform: Default::default(),
 | 
					            transform: Default::default(),
 | 
				
			||||||
            translation: Default::default(),
 | 
					            local_transform: Default::default(),
 | 
				
			||||||
            rotation: Default::default(),
 | 
					 | 
				
			||||||
            scale: Default::default(),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@ pub use render::*;
 | 
				
			|||||||
pub mod prelude {
 | 
					pub mod prelude {
 | 
				
			||||||
    pub use crate::{
 | 
					    pub use crate::{
 | 
				
			||||||
        entity::*,
 | 
					        entity::*,
 | 
				
			||||||
        widget::{Button, Label},
 | 
					        widget::{Button, Text},
 | 
				
			||||||
        Anchors, Click, Hover, Margins, Node,
 | 
					        Anchors, Click, Hover, Margins, Node,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -25,7 +25,6 @@ use bevy_app::prelude::*;
 | 
				
			|||||||
use bevy_ecs::IntoQuerySystem;
 | 
					use bevy_ecs::IntoQuerySystem;
 | 
				
			||||||
use bevy_render::render_graph::RenderGraph;
 | 
					use bevy_render::render_graph::RenderGraph;
 | 
				
			||||||
use update::ui_update_system;
 | 
					use update::ui_update_system;
 | 
				
			||||||
use widget::Label;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Default)]
 | 
					#[derive(Default)]
 | 
				
			||||||
pub struct UiPlugin;
 | 
					pub struct UiPlugin;
 | 
				
			||||||
@ -34,8 +33,8 @@ impl AppPlugin for UiPlugin {
 | 
				
			|||||||
    fn build(&self, app: &mut AppBuilder) {
 | 
					    fn build(&self, app: &mut AppBuilder) {
 | 
				
			||||||
        app.add_system_to_stage(stage::PRE_UPDATE, ui_focus_system.system())
 | 
					        app.add_system_to_stage(stage::PRE_UPDATE, ui_focus_system.system())
 | 
				
			||||||
            .add_system_to_stage(stage::POST_UPDATE, ui_update_system.system())
 | 
					            .add_system_to_stage(stage::POST_UPDATE, ui_update_system.system())
 | 
				
			||||||
            .add_system_to_stage(stage::POST_UPDATE, Label::label_system.system())
 | 
					            .add_system_to_stage(stage::POST_UPDATE, widget::text_system.system())
 | 
				
			||||||
            .add_system_to_stage(bevy_render::stage::DRAW, Label::draw_label_system.system());
 | 
					            .add_system_to_stage(bevy_render::stage::DRAW, widget::draw_text_system.system());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let resources = app.resources();
 | 
					        let resources = app.resources();
 | 
				
			||||||
        let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
 | 
					        let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
use super::{Anchors, Margins};
 | 
					use super::{Anchors, Margins};
 | 
				
			||||||
use bevy_math::{Vec2, Vec3};
 | 
					use bevy_math::{Mat4, Vec2, Vec3};
 | 
				
			||||||
use bevy_render::renderer::RenderResources;
 | 
					use bevy_render::renderer::RenderResources;
 | 
				
			||||||
use bevy_transform::prelude::Translation;
 | 
					use bevy_transform::components::LocalTransform;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
enum MarginGrowDirection {
 | 
					enum MarginGrowDirection {
 | 
				
			||||||
@ -38,7 +38,12 @@ impl Node {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn update(&mut self, translation: &mut Translation, z_offset: f32, parent_size: Vec2) {
 | 
					    pub fn update(
 | 
				
			||||||
 | 
					        &mut self,
 | 
				
			||||||
 | 
					        local_transform: &mut LocalTransform,
 | 
				
			||||||
 | 
					        z_offset: f32,
 | 
				
			||||||
 | 
					        parent_size: Vec2,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
        let (quad_x, quad_width) = Self::compute_dimension_properties(
 | 
					        let (quad_x, quad_width) = Self::compute_dimension_properties(
 | 
				
			||||||
            self.margins.left,
 | 
					            self.margins.left,
 | 
				
			||||||
            self.margins.right,
 | 
					            self.margins.right,
 | 
				
			||||||
@ -55,8 +60,10 @@ impl Node {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.size = Vec2::new(quad_width, quad_height);
 | 
					        self.size = Vec2::new(quad_width, quad_height);
 | 
				
			||||||
        translation.0 = self.position.extend(0.0) + Vec3::new(quad_x, quad_y, z_offset)
 | 
					        local_transform.0 = Mat4::from_translation(
 | 
				
			||||||
            - (parent_size / 2.0).extend(0.0);
 | 
					            self.position.extend(z_offset) + Vec3::new(quad_x, quad_y, z_offset)
 | 
				
			||||||
 | 
					                - (parent_size / 2.0).extend(0.0),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn compute_dimension_properties(
 | 
					    fn compute_dimension_properties(
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ use bevy_ecs::{Entity, Query, Res, Without};
 | 
				
			|||||||
use bevy_math::Vec2;
 | 
					use bevy_math::Vec2;
 | 
				
			||||||
use bevy_transform::{
 | 
					use bevy_transform::{
 | 
				
			||||||
    hierarchy,
 | 
					    hierarchy,
 | 
				
			||||||
    prelude::{Children, Parent, Translation},
 | 
					    prelude::{Children, LocalTransform, Parent},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use bevy_window::Windows;
 | 
					use bevy_window::Windows;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,8 +17,8 @@ pub struct Rect {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub fn ui_update_system(
 | 
					pub fn ui_update_system(
 | 
				
			||||||
    windows: Res<Windows>,
 | 
					    windows: Res<Windows>,
 | 
				
			||||||
    mut orphan_node_query: Query<Without<Parent, (Entity, &mut Node, &mut Translation)>>,
 | 
					    mut orphan_node_query: Query<Without<Parent, (Entity, &mut Node, &mut LocalTransform)>>,
 | 
				
			||||||
    mut node_query: Query<(Entity, &mut Node, &mut Translation)>,
 | 
					    mut node_query: Query<(Entity, &mut Node, &mut LocalTransform)>,
 | 
				
			||||||
    children_query: Query<&Children>,
 | 
					    children_query: Query<&Children>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    let window_size = if let Some(window) = windows.get_primary() {
 | 
					    let window_size = if let Some(window) = windows.get_primary() {
 | 
				
			||||||
@ -53,21 +53,20 @@ pub fn ui_update_system(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn update_node_entity(
 | 
					fn update_node_entity(
 | 
				
			||||||
    node_query: &mut Query<(Entity, &mut Node, &mut Translation)>,
 | 
					    node_query: &mut Query<(Entity, &mut Node, &mut LocalTransform)>,
 | 
				
			||||||
    entity: Entity,
 | 
					    entity: Entity,
 | 
				
			||||||
    parent_rect: Option<&mut Rect>,
 | 
					    parent_rect: Option<&mut Rect>,
 | 
				
			||||||
    previous_rect: Option<Rect>,
 | 
					    previous_rect: Option<Rect>,
 | 
				
			||||||
) -> Option<Rect> {
 | 
					) -> Option<Rect> {
 | 
				
			||||||
    if let Ok(mut node) = node_query.get_mut::<Node>(entity) {
 | 
					    if let Ok(mut node) = node_query.get_mut::<Node>(entity) {
 | 
				
			||||||
        if let Ok(mut translation) = node_query.get_mut::<Translation>(entity) {
 | 
					        if let Ok(mut local_transform) = node_query.get_mut::<LocalTransform>(entity) {
 | 
				
			||||||
            let parent_rect = parent_rect.unwrap();
 | 
					            let parent_rect = parent_rect.unwrap();
 | 
				
			||||||
            let mut z = parent_rect.z;
 | 
					            let mut z = UI_Z_STEP;
 | 
				
			||||||
            if let Some(previous_rect) = previous_rect {
 | 
					            if let Some(previous_rect) = previous_rect {
 | 
				
			||||||
                z = previous_rect.z
 | 
					                z += previous_rect.z
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            z += UI_Z_STEP;
 | 
					            node.update(&mut local_transform, z, parent_rect.size);
 | 
				
			||||||
            node.update(&mut translation, z + parent_rect.z, parent_rect.size);
 | 
					 | 
				
			||||||
            return Some(Rect { size: node.size, z });
 | 
					            return Some(Rect { size: node.size, z });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,77 +0,0 @@
 | 
				
			|||||||
use crate::Node;
 | 
					 | 
				
			||||||
use bevy_asset::{Assets, Handle};
 | 
					 | 
				
			||||||
use bevy_ecs::{Query, Res, ResMut};
 | 
					 | 
				
			||||||
use bevy_render::{
 | 
					 | 
				
			||||||
    draw::{Draw, DrawContext, Drawable},
 | 
					 | 
				
			||||||
    renderer::{AssetRenderResourceBindings, RenderResourceBindings},
 | 
					 | 
				
			||||||
    texture::Texture,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
use bevy_sprite::TextureAtlas;
 | 
					 | 
				
			||||||
use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
 | 
					 | 
				
			||||||
use bevy_transform::prelude::Transform;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Default)]
 | 
					 | 
				
			||||||
pub struct Label {
 | 
					 | 
				
			||||||
    pub text: String,
 | 
					 | 
				
			||||||
    pub font: Handle<Font>,
 | 
					 | 
				
			||||||
    pub style: TextStyle,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Label {
 | 
					 | 
				
			||||||
    pub fn label_system(
 | 
					 | 
				
			||||||
        mut textures: ResMut<Assets<Texture>>,
 | 
					 | 
				
			||||||
        fonts: Res<Assets<Font>>,
 | 
					 | 
				
			||||||
        mut font_atlas_sets: ResMut<Assets<FontAtlasSet>>,
 | 
					 | 
				
			||||||
        mut texture_atlases: ResMut<Assets<TextureAtlas>>,
 | 
					 | 
				
			||||||
        mut query: Query<&Label>,
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        for label in &mut query.iter() {
 | 
					 | 
				
			||||||
            let font_atlases = font_atlas_sets
 | 
					 | 
				
			||||||
                .get_or_insert_with(Handle::from_id(label.font.id), || {
 | 
					 | 
				
			||||||
                    FontAtlasSet::new(label.font)
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            // TODO: this call results in one or more TextureAtlases, whose render resources are created in the RENDER_GRAPH_SYSTEMS
 | 
					 | 
				
			||||||
            // stage. That logic runs _before_ the DRAW stage, which means we cant call add_glyphs_to_atlas in the draw stage
 | 
					 | 
				
			||||||
            // without our render resources being a frame behind. Therefore glyph atlasing either needs its own system or the TextureAtlas
 | 
					 | 
				
			||||||
            // resource generation needs to happen AFTER the render graph systems. maybe draw systems should execute within the
 | 
					 | 
				
			||||||
            // render graph so ordering like this can be taken into account? Maybe the RENDER_GRAPH_SYSTEMS stage should be removed entirely
 | 
					 | 
				
			||||||
            // in favor of node.update()? Regardless, in the immediate short term the current approach is fine.
 | 
					 | 
				
			||||||
            font_atlases.add_glyphs_to_atlas(
 | 
					 | 
				
			||||||
                &fonts,
 | 
					 | 
				
			||||||
                &mut texture_atlases,
 | 
					 | 
				
			||||||
                &mut textures,
 | 
					 | 
				
			||||||
                label.style.font_size,
 | 
					 | 
				
			||||||
                &label.text,
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn draw_label_system(
 | 
					 | 
				
			||||||
        mut draw_context: DrawContext,
 | 
					 | 
				
			||||||
        fonts: Res<Assets<Font>>,
 | 
					 | 
				
			||||||
        font_atlas_sets: Res<Assets<FontAtlasSet>>,
 | 
					 | 
				
			||||||
        texture_atlases: Res<Assets<TextureAtlas>>,
 | 
					 | 
				
			||||||
        mut render_resource_bindings: ResMut<RenderResourceBindings>,
 | 
					 | 
				
			||||||
        mut asset_render_resource_bindings: ResMut<AssetRenderResourceBindings>,
 | 
					 | 
				
			||||||
        mut query: Query<(&mut Draw, &Label, &Node, &Transform)>,
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        for (mut draw, label, node, transform) in &mut query.iter() {
 | 
					 | 
				
			||||||
            let position = transform.value.w_axis().truncate() - (node.size / 2.0).extend(0.0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let mut drawable_text = DrawableText {
 | 
					 | 
				
			||||||
                font: fonts.get(&label.font).unwrap(),
 | 
					 | 
				
			||||||
                font_atlas_set: font_atlas_sets
 | 
					 | 
				
			||||||
                    .get(&label.font.as_handle::<FontAtlasSet>())
 | 
					 | 
				
			||||||
                    .unwrap(),
 | 
					 | 
				
			||||||
                texture_atlases: &texture_atlases,
 | 
					 | 
				
			||||||
                render_resource_bindings: &mut render_resource_bindings,
 | 
					 | 
				
			||||||
                asset_render_resource_bindings: &mut asset_render_resource_bindings,
 | 
					 | 
				
			||||||
                position,
 | 
					 | 
				
			||||||
                style: &label.style,
 | 
					 | 
				
			||||||
                text: &label.text,
 | 
					 | 
				
			||||||
                container_size: node.size,
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            drawable_text.draw(&mut draw, &mut draw_context).unwrap();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
mod button;
 | 
					mod button;
 | 
				
			||||||
mod label;
 | 
					mod text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use button::*;
 | 
					pub use button::*;
 | 
				
			||||||
pub use label::*;
 | 
					pub use text::*;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										75
									
								
								crates/bevy_ui/src/widget/text.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								crates/bevy_ui/src/widget/text.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					use crate::Node;
 | 
				
			||||||
 | 
					use bevy_asset::{Assets, Handle};
 | 
				
			||||||
 | 
					use bevy_ecs::{Query, Res, ResMut};
 | 
				
			||||||
 | 
					use bevy_render::{
 | 
				
			||||||
 | 
					    draw::{Draw, DrawContext, Drawable},
 | 
				
			||||||
 | 
					    renderer::{AssetRenderResourceBindings, RenderResourceBindings},
 | 
				
			||||||
 | 
					    texture::Texture,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use bevy_sprite::TextureAtlas;
 | 
				
			||||||
 | 
					use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
 | 
				
			||||||
 | 
					use bevy_transform::prelude::Transform;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Default)]
 | 
				
			||||||
 | 
					pub struct Text {
 | 
				
			||||||
 | 
					    pub value: String,
 | 
				
			||||||
 | 
					    pub font: Handle<Font>,
 | 
				
			||||||
 | 
					    pub style: TextStyle,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn text_system(
 | 
				
			||||||
 | 
					    mut textures: ResMut<Assets<Texture>>,
 | 
				
			||||||
 | 
					    fonts: Res<Assets<Font>>,
 | 
				
			||||||
 | 
					    mut font_atlas_sets: ResMut<Assets<FontAtlasSet>>,
 | 
				
			||||||
 | 
					    mut texture_atlases: ResMut<Assets<TextureAtlas>>,
 | 
				
			||||||
 | 
					    mut query: Query<&Text>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    for text in &mut query.iter() {
 | 
				
			||||||
 | 
					        let font_atlases = font_atlas_sets
 | 
				
			||||||
 | 
					            .get_or_insert_with(Handle::from_id(text.font.id), || {
 | 
				
			||||||
 | 
					                FontAtlasSet::new(text.font)
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        // TODO: this call results in one or more TextureAtlases, whose render resources are created in the RENDER_GRAPH_SYSTEMS
 | 
				
			||||||
 | 
					        // stage. That logic runs _before_ the DRAW stage, which means we cant call add_glyphs_to_atlas in the draw stage
 | 
				
			||||||
 | 
					        // without our render resources being a frame behind. Therefore glyph atlasing either needs its own system or the TextureAtlas
 | 
				
			||||||
 | 
					        // resource generation needs to happen AFTER the render graph systems. maybe draw systems should execute within the
 | 
				
			||||||
 | 
					        // render graph so ordering like this can be taken into account? Maybe the RENDER_GRAPH_SYSTEMS stage should be removed entirely
 | 
				
			||||||
 | 
					        // in favor of node.update()? Regardless, in the immediate short term the current approach is fine.
 | 
				
			||||||
 | 
					        font_atlases.add_glyphs_to_atlas(
 | 
				
			||||||
 | 
					            &fonts,
 | 
				
			||||||
 | 
					            &mut texture_atlases,
 | 
				
			||||||
 | 
					            &mut textures,
 | 
				
			||||||
 | 
					            text.style.font_size,
 | 
				
			||||||
 | 
					            &text.value,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn draw_text_system(
 | 
				
			||||||
 | 
					    mut draw_context: DrawContext,
 | 
				
			||||||
 | 
					    fonts: Res<Assets<Font>>,
 | 
				
			||||||
 | 
					    font_atlas_sets: Res<Assets<FontAtlasSet>>,
 | 
				
			||||||
 | 
					    texture_atlases: Res<Assets<TextureAtlas>>,
 | 
				
			||||||
 | 
					    mut render_resource_bindings: ResMut<RenderResourceBindings>,
 | 
				
			||||||
 | 
					    mut asset_render_resource_bindings: ResMut<AssetRenderResourceBindings>,
 | 
				
			||||||
 | 
					    mut query: Query<(&mut Draw, &Text, &Node, &Transform)>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    for (mut draw, text, node, transform) in &mut query.iter() {
 | 
				
			||||||
 | 
					        let position = transform.value.w_axis().truncate() - (node.size / 2.0).extend(0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut drawable_text = DrawableText {
 | 
				
			||||||
 | 
					            font: fonts.get(&text.font).unwrap(),
 | 
				
			||||||
 | 
					            font_atlas_set: font_atlas_sets
 | 
				
			||||||
 | 
					                .get(&text.font.as_handle::<FontAtlasSet>())
 | 
				
			||||||
 | 
					                .unwrap(),
 | 
				
			||||||
 | 
					            texture_atlases: &texture_atlases,
 | 
				
			||||||
 | 
					            render_resource_bindings: &mut render_resource_bindings,
 | 
				
			||||||
 | 
					            asset_render_resource_bindings: &mut asset_render_resource_bindings,
 | 
				
			||||||
 | 
					            position,
 | 
				
			||||||
 | 
					            style: &text.style,
 | 
				
			||||||
 | 
					            text: &text.value,
 | 
				
			||||||
 | 
					            container_size: node.size,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        drawable_text.draw(&mut draw, &mut draw_context).unwrap();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -64,10 +64,10 @@ fn setup(
 | 
				
			|||||||
            velocity: 400.0 * Vec3::new(0.5, -0.5, 0.0).normalize(),
 | 
					            velocity: 400.0 * Vec3::new(0.5, -0.5, 0.0).normalize(),
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        // scoreboard
 | 
					        // scoreboard
 | 
				
			||||||
        .spawn(LabelComponents {
 | 
					        .spawn(TextComponents {
 | 
				
			||||||
            label: Label {
 | 
					            text: Text {
 | 
				
			||||||
                font: asset_server.load("assets/fonts/FiraSans-Bold.ttf").unwrap(),
 | 
					                font: asset_server.load("assets/fonts/FiraSans-Bold.ttf").unwrap(),
 | 
				
			||||||
                text: "Score:".to_string(),
 | 
					                value: "Score:".to_string(),
 | 
				
			||||||
                style: TextStyle {
 | 
					                style: TextStyle {
 | 
				
			||||||
                    color: Color::rgb(0.2, 0.2, 0.8).into(),
 | 
					                    color: Color::rgb(0.2, 0.2, 0.8).into(),
 | 
				
			||||||
                    font_size: 40.0,
 | 
					                    font_size: 40.0,
 | 
				
			||||||
@ -180,9 +180,9 @@ fn ball_movement_system(time: Res<Time>, mut ball_query: Query<(&Ball, &mut Tran
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn scoreboard_system(scoreboard: Res<Scoreboard>, mut query: Query<&mut Label>) {
 | 
					fn scoreboard_system(scoreboard: Res<Scoreboard>, mut query: Query<&mut Text>) {
 | 
				
			||||||
    for mut label in &mut query.iter() {
 | 
					    for mut text in &mut query.iter() {
 | 
				
			||||||
        label.text = format!("Score: {}", scoreboard.score);
 | 
					        text.value = format!("Score: {}", scoreboard.score);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -50,11 +50,11 @@ fn atlas_render_system(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn text_update_system(mut state: ResMut<State>, time: Res<Time>, mut query: Query<&mut Label>) {
 | 
					fn text_update_system(mut state: ResMut<State>, time: Res<Time>, mut query: Query<&mut Text>) {
 | 
				
			||||||
    for mut label in &mut query.iter() {
 | 
					    for mut text in &mut query.iter() {
 | 
				
			||||||
        state.timer.tick(time.delta_seconds);
 | 
					        state.timer.tick(time.delta_seconds);
 | 
				
			||||||
        if state.timer.finished {
 | 
					        if state.timer.finished {
 | 
				
			||||||
            label.text = format!("{}", rand::random::<u8>() as char);
 | 
					            text.value = format!("{}", rand::random::<u8>() as char);
 | 
				
			||||||
            state.timer.reset();
 | 
					            state.timer.reset();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -67,10 +67,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut state: ResM
 | 
				
			|||||||
        // 2d camera
 | 
					        // 2d camera
 | 
				
			||||||
        .spawn(Camera2dComponents::default())
 | 
					        .spawn(Camera2dComponents::default())
 | 
				
			||||||
        // texture
 | 
					        // texture
 | 
				
			||||||
        .spawn(LabelComponents {
 | 
					        .spawn(TextComponents {
 | 
				
			||||||
            node: Node::new(Anchors::TOP_LEFT, Margins::new(0.0, 250.0, 0.0, 60.0)),
 | 
					            node: Node::new(Anchors::TOP_LEFT, Margins::new(0.0, 250.0, 0.0, 60.0)),
 | 
				
			||||||
            label: Label {
 | 
					            text: Text {
 | 
				
			||||||
                text: "a".to_string(),
 | 
					                value: "a".to_string(),
 | 
				
			||||||
                font: font_handle,
 | 
					                font: font_handle,
 | 
				
			||||||
                style: TextStyle {
 | 
					                style: TextStyle {
 | 
				
			||||||
                    font_size: 60.0,
 | 
					                    font_size: 60.0,
 | 
				
			||||||
 | 
				
			|||||||
@ -12,11 +12,11 @@ fn main() {
 | 
				
			|||||||
        .run();
 | 
					        .run();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn text_update_system(diagnostics: Res<Diagnostics>, mut query: Query<&mut Label>) {
 | 
					fn text_update_system(diagnostics: Res<Diagnostics>, mut query: Query<&mut Text>) {
 | 
				
			||||||
    for mut label in &mut query.iter() {
 | 
					    for mut text in &mut query.iter() {
 | 
				
			||||||
        if let Some(fps) = diagnostics.get(FrameTimeDiagnosticsPlugin::FPS) {
 | 
					        if let Some(fps) = diagnostics.get(FrameTimeDiagnosticsPlugin::FPS) {
 | 
				
			||||||
            if let Some(average) = fps.average() {
 | 
					            if let Some(average) = fps.average() {
 | 
				
			||||||
                label.text = format!("FPS: {:.2}", average);
 | 
					                text.value = format!("FPS: {:.2}", average);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -28,10 +28,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
 | 
				
			|||||||
        // 2d camera
 | 
					        // 2d camera
 | 
				
			||||||
        .spawn(Camera2dComponents::default())
 | 
					        .spawn(Camera2dComponents::default())
 | 
				
			||||||
        // texture
 | 
					        // texture
 | 
				
			||||||
        .spawn(LabelComponents {
 | 
					        .spawn(TextComponents {
 | 
				
			||||||
            node: Node::new(Anchors::TOP_LEFT, Margins::new(0.0, 250.0, 0.0, 60.0)),
 | 
					            node: Node::new(Anchors::TOP_LEFT, Margins::new(0.0, 250.0, 0.0, 60.0)),
 | 
				
			||||||
            label: Label {
 | 
					            text: Text {
 | 
				
			||||||
                text: "FPS:".to_string(),
 | 
					                value: "FPS:".to_string(),
 | 
				
			||||||
                font: font_handle,
 | 
					                font: font_handle,
 | 
				
			||||||
                style: TextStyle {
 | 
					                style: TextStyle {
 | 
				
			||||||
                    font_size: 60.0,
 | 
					                    font_size: 60.0,
 | 
				
			||||||
 | 
				
			|||||||
@ -39,10 +39,10 @@ fn setup(
 | 
				
			|||||||
                    ..Default::default()
 | 
					                    ..Default::default()
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .with_children(|parent| {
 | 
					                .with_children(|parent| {
 | 
				
			||||||
                    parent.spawn(LabelComponents {
 | 
					                    parent.spawn(TextComponents {
 | 
				
			||||||
                        node: Node::new(Anchors::TOP_LEFT, Margins::new(10.0, 200.0, 40.0, 10.0)),
 | 
					                        node: Node::new(Anchors::TOP_LEFT, Margins::new(10.0, 200.0, 40.0, 10.0)),
 | 
				
			||||||
                        label: Label {
 | 
					                        text: Text {
 | 
				
			||||||
                            text: "Text Label".to_string(),
 | 
					                            value: "Text Example".to_string(),
 | 
				
			||||||
                            font: font_handle,
 | 
					                            font: font_handle,
 | 
				
			||||||
                            style: TextStyle {
 | 
					                            style: TextStyle {
 | 
				
			||||||
                                font_size: 30.0,
 | 
					                                font_size: 30.0,
 | 
				
			||||||
@ -121,6 +121,10 @@ fn setup(
 | 
				
			|||||||
                        Margins::new(0.0, 100.0, 0.0, 100.0),
 | 
					                        Margins::new(0.0, 100.0, 0.0, 100.0),
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                    material: materials.add(Color::rgba(1.0, 0.9, 0.9, 0.4).into()),
 | 
					                    material: materials.add(Color::rgba(1.0, 0.9, 0.9, 0.4).into()),
 | 
				
			||||||
 | 
					                    draw: Draw {
 | 
				
			||||||
 | 
					                        is_transparent: true,
 | 
				
			||||||
 | 
					                        ..Default::default()
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
                    ..Default::default()
 | 
					                    ..Default::default()
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                // texture
 | 
					                // texture
 | 
				
			||||||
@ -130,6 +134,10 @@ fn setup(
 | 
				
			|||||||
                        Margins::new(-250.0, 250.0, 510.0 * aspect, 10.0),
 | 
					                        Margins::new(-250.0, 250.0, 510.0 * aspect, 10.0),
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                    material: materials.add(ColorMaterial::texture(texture_handle)),
 | 
					                    material: materials.add(ColorMaterial::texture(texture_handle)),
 | 
				
			||||||
 | 
					                    draw: Draw {
 | 
				
			||||||
 | 
					                        is_transparent: true,
 | 
				
			||||||
 | 
					                        ..Default::default()
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
                    ..Default::default()
 | 
					                    ..Default::default()
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user