mirror of
https://github.com/bevyengine/bevy
synced 2024-11-23 21:23:05 +00:00
split up TextStyle
(#15857)
# Objective Currently text is recomputed unnecessarily on any changes to its color, which is extremely expensive. ## Solution Split up `TextStyle` into two separate components `TextFont` and `TextColor`. ## Testing I added this system to `many_buttons`: ```rust fn set_text_colors_changed(mut colors: Query<&mut TextColor>) { for mut text_color in colors.iter_mut() { text_color.set_changed(); } } ``` reports ~4fps on main, ~50fps with this PR. ## Migration Guide `TextStyle` has been renamed to `TextFont` and its `color` field has been moved to a separate component named `TextColor` which newtypes `Color`.
This commit is contained in:
parent
6521e759ea
commit
6f7d0e5725
83 changed files with 752 additions and 641 deletions
|
@ -14,7 +14,7 @@ use bevy_ecs::{
|
|||
};
|
||||
use bevy_hierarchy::{BuildChildren, ChildBuild};
|
||||
use bevy_render::view::Visibility;
|
||||
use bevy_text::{Font, TextSpan, TextStyle};
|
||||
use bevy_text::{Font, TextColor, TextFont, TextSpan};
|
||||
use bevy_ui::{
|
||||
node_bundles::NodeBundle,
|
||||
widget::{Text, UiTextWriter},
|
||||
|
@ -62,7 +62,9 @@ impl Plugin for FpsOverlayPlugin {
|
|||
#[derive(Resource, Clone)]
|
||||
pub struct FpsOverlayConfig {
|
||||
/// Configuration of text in the overlay.
|
||||
pub text_config: TextStyle,
|
||||
pub text_config: TextFont,
|
||||
/// Color of text in the overlay.
|
||||
pub text_color: Color,
|
||||
/// Displays the FPS overlay if true.
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
@ -70,12 +72,12 @@ pub struct FpsOverlayConfig {
|
|||
impl Default for FpsOverlayConfig {
|
||||
fn default() -> Self {
|
||||
FpsOverlayConfig {
|
||||
text_config: TextStyle {
|
||||
text_config: TextFont {
|
||||
font: Handle::<Font>::default(),
|
||||
font_size: 32.0,
|
||||
color: Color::WHITE,
|
||||
..default()
|
||||
},
|
||||
text_color: Color::WHITE,
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +104,7 @@ fn setup(mut commands: Commands, overlay_config: Res<FpsOverlayConfig>) {
|
|||
p.spawn((
|
||||
Text::new("FPS: "),
|
||||
overlay_config.text_config.clone(),
|
||||
TextColor(overlay_config.text_color),
|
||||
FpsText,
|
||||
))
|
||||
.with_child((TextSpan::default(), overlay_config.text_config.clone()));
|
||||
|
@ -128,9 +131,10 @@ fn customize_text(
|
|||
mut writer: UiTextWriter,
|
||||
) {
|
||||
for entity in &query {
|
||||
writer.for_each_style(entity, |mut style| {
|
||||
*style = overlay_config.text_config.clone();
|
||||
writer.for_each_font(entity, |mut font| {
|
||||
*font = overlay_config.text_config.clone();
|
||||
});
|
||||
writer.for_each_color(entity, |mut color| color.0 = overlay_config.text_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,9 +60,9 @@ pub struct FontAtlasKey(pub u32, pub FontSmoothing);
|
|||
/// A `FontAtlasSet` is an [`Asset`].
|
||||
///
|
||||
/// There is one `FontAtlasSet` for each font:
|
||||
/// - When a [`Font`] is loaded as an asset and then used in [`TextStyle`](crate::TextStyle),
|
||||
/// - When a [`Font`] is loaded as an asset and then used in [`TextFont`](crate::TextFont),
|
||||
/// a `FontAtlasSet` asset is created from a weak handle to the `Font`.
|
||||
/// - ~When a font is loaded as a system font, and then used in [`TextStyle`](crate::TextStyle),
|
||||
/// - ~When a font is loaded as a system font, and then used in [`TextFont`](crate::TextFont),
|
||||
/// a `FontAtlasSet` asset is created and stored with a strong handle to the `FontAtlasSet`.~
|
||||
/// (*Note that system fonts are not currently supported by the `TextPipeline`.*)
|
||||
///
|
||||
|
|
|
@ -65,8 +65,8 @@ pub use text_access::*;
|
|||
pub mod prelude {
|
||||
#[doc(hidden)]
|
||||
pub use crate::{
|
||||
Font, JustifyText, LineBreak, Text2d, TextError, TextLayout, TextReader2d, TextSpan,
|
||||
TextStyle, TextWriter2d,
|
||||
Font, JustifyText, LineBreak, Text2d, TextColor, TextError, TextFont, TextLayout,
|
||||
TextReader2d, TextSpan, TextWriter2d,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use alloc::sync::Arc;
|
||||
|
||||
use bevy_asset::{AssetId, Assets};
|
||||
use bevy_color::Color;
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
|
@ -17,7 +18,7 @@ use cosmic_text::{Attrs, Buffer, Family, Metrics, Shaping, Wrap};
|
|||
|
||||
use crate::{
|
||||
error::TextError, ComputedTextBlock, Font, FontAtlasSets, FontSmoothing, JustifyText,
|
||||
LineBreak, PositionedGlyph, TextBounds, TextEntity, TextLayout, TextStyle, YAxisOrientation,
|
||||
LineBreak, PositionedGlyph, TextBounds, TextEntity, TextFont, TextLayout, YAxisOrientation,
|
||||
};
|
||||
|
||||
/// A wrapper resource around a [`cosmic_text::FontSystem`]
|
||||
|
@ -70,7 +71,7 @@ pub struct TextPipeline {
|
|||
/// Buffered vec for collecting spans.
|
||||
///
|
||||
/// See [this dark magic](https://users.rust-lang.org/t/how-to-cache-a-vectors-capacity/94478/10).
|
||||
spans_buffer: Vec<(usize, &'static str, &'static TextStyle, FontFaceInfo)>,
|
||||
spans_buffer: Vec<(usize, &'static str, &'static TextFont, FontFaceInfo)>,
|
||||
/// Buffered vec for collecting info for glyph assembly.
|
||||
glyph_info: Vec<(AssetId<Font>, FontSmoothing)>,
|
||||
}
|
||||
|
@ -83,7 +84,7 @@ impl TextPipeline {
|
|||
pub fn update_buffer<'a>(
|
||||
&mut self,
|
||||
fonts: &Assets<Font>,
|
||||
text_spans: impl Iterator<Item = (Entity, usize, &'a str, &'a TextStyle)>,
|
||||
text_spans: impl Iterator<Item = (Entity, usize, &'a str, &'a TextFont, Color)>,
|
||||
linebreak: LineBreak,
|
||||
justify: JustifyText,
|
||||
bounds: TextBounds,
|
||||
|
@ -96,22 +97,22 @@ impl TextPipeline {
|
|||
// Collect span information into a vec. This is necessary because font loading requires mut access
|
||||
// to FontSystem, which the cosmic-text Buffer also needs.
|
||||
let mut font_size: f32 = 0.;
|
||||
let mut spans: Vec<(usize, &str, &TextStyle, FontFaceInfo)> =
|
||||
let mut spans: Vec<(usize, &str, &TextFont, FontFaceInfo, Color)> =
|
||||
core::mem::take(&mut self.spans_buffer)
|
||||
.into_iter()
|
||||
.map(|_| -> (usize, &str, &TextStyle, FontFaceInfo) { unreachable!() })
|
||||
.map(|_| -> (usize, &str, &TextFont, FontFaceInfo, Color) { unreachable!() })
|
||||
.collect();
|
||||
|
||||
computed.entities.clear();
|
||||
|
||||
for (span_index, (entity, depth, span, style)) in text_spans.enumerate() {
|
||||
for (span_index, (entity, depth, span, text_font, color)) in text_spans.enumerate() {
|
||||
// Return early if a font is not loaded yet.
|
||||
if !fonts.contains(style.font.id()) {
|
||||
if !fonts.contains(text_font.font.id()) {
|
||||
spans.clear();
|
||||
self.spans_buffer = spans
|
||||
.into_iter()
|
||||
.map(
|
||||
|_| -> (usize, &'static str, &'static TextStyle, FontFaceInfo) {
|
||||
|_| -> (usize, &'static str, &'static TextFont, FontFaceInfo) {
|
||||
unreachable!()
|
||||
},
|
||||
)
|
||||
|
@ -124,17 +125,21 @@ impl TextPipeline {
|
|||
computed.entities.push(TextEntity { entity, depth });
|
||||
|
||||
// Get max font size for use in cosmic Metrics.
|
||||
font_size = font_size.max(style.font_size);
|
||||
font_size = font_size.max(text_font.font_size);
|
||||
|
||||
// Load Bevy fonts into cosmic-text's font system.
|
||||
let face_info =
|
||||
load_font_to_fontdb(style, font_system, &mut self.map_handle_to_font_id, fonts);
|
||||
let face_info = load_font_to_fontdb(
|
||||
text_font,
|
||||
font_system,
|
||||
&mut self.map_handle_to_font_id,
|
||||
fonts,
|
||||
);
|
||||
|
||||
// Save spans that aren't zero-sized.
|
||||
if scale_factor <= 0.0 || style.font_size <= 0.0 {
|
||||
if scale_factor <= 0.0 || text_font.font_size <= 0.0 {
|
||||
continue;
|
||||
}
|
||||
spans.push((span_index, span, style, face_info));
|
||||
spans.push((span_index, span, text_font, face_info, color));
|
||||
}
|
||||
|
||||
let line_height = font_size * 1.2;
|
||||
|
@ -151,12 +156,14 @@ impl TextPipeline {
|
|||
// The section index is stored in the metadata of the spans, and could be used
|
||||
// to look up the section the span came from and is not used internally
|
||||
// in cosmic-text.
|
||||
let spans_iter = spans.iter().map(|(span_index, span, style, font_info)| {
|
||||
(
|
||||
*span,
|
||||
get_attrs(*span_index, style, font_info, scale_factor),
|
||||
)
|
||||
});
|
||||
let spans_iter = spans
|
||||
.iter()
|
||||
.map(|(span_index, span, text_font, font_info, color)| {
|
||||
(
|
||||
*span,
|
||||
get_attrs(*span_index, text_font, *color, font_info, scale_factor),
|
||||
)
|
||||
});
|
||||
|
||||
// Update the buffer.
|
||||
let buffer = &mut computed.buffer;
|
||||
|
@ -186,7 +193,7 @@ impl TextPipeline {
|
|||
spans.clear();
|
||||
self.spans_buffer = spans
|
||||
.into_iter()
|
||||
.map(|_| -> (usize, &'static str, &'static TextStyle, FontFaceInfo) { unreachable!() })
|
||||
.map(|_| -> (usize, &'static str, &'static TextFont, FontFaceInfo) { unreachable!() })
|
||||
.collect();
|
||||
|
||||
Ok(())
|
||||
|
@ -201,7 +208,7 @@ impl TextPipeline {
|
|||
&mut self,
|
||||
layout_info: &mut TextLayoutInfo,
|
||||
fonts: &Assets<Font>,
|
||||
text_spans: impl Iterator<Item = (Entity, usize, &'a str, &'a TextStyle)>,
|
||||
text_spans: impl Iterator<Item = (Entity, usize, &'a str, &'a TextFont, Color)>,
|
||||
scale_factor: f64,
|
||||
layout: &TextLayout,
|
||||
bounds: TextBounds,
|
||||
|
@ -222,8 +229,8 @@ impl TextPipeline {
|
|||
// Extract font ids from the iterator while traversing it.
|
||||
let mut glyph_info = core::mem::take(&mut self.glyph_info);
|
||||
glyph_info.clear();
|
||||
let text_spans = text_spans.inspect(|(_, _, _, style)| {
|
||||
glyph_info.push((style.font.id(), style.font_smoothing));
|
||||
let text_spans = text_spans.inspect(|(_, _, _, text_font, _)| {
|
||||
glyph_info.push((text_font.font.id(), text_font.font_smoothing));
|
||||
});
|
||||
|
||||
let update_result = self.update_buffer(
|
||||
|
@ -335,7 +342,7 @@ impl TextPipeline {
|
|||
&mut self,
|
||||
entity: Entity,
|
||||
fonts: &Assets<Font>,
|
||||
text_spans: impl Iterator<Item = (Entity, usize, &'a str, &'a TextStyle)>,
|
||||
text_spans: impl Iterator<Item = (Entity, usize, &'a str, &'a TextFont, Color)>,
|
||||
scale_factor: f64,
|
||||
layout: &TextLayout,
|
||||
computed: &mut ComputedTextBlock,
|
||||
|
@ -427,12 +434,12 @@ impl TextMeasureInfo {
|
|||
}
|
||||
|
||||
fn load_font_to_fontdb(
|
||||
style: &TextStyle,
|
||||
text_font: &TextFont,
|
||||
font_system: &mut cosmic_text::FontSystem,
|
||||
map_handle_to_font_id: &mut HashMap<AssetId<Font>, (cosmic_text::fontdb::ID, Arc<str>)>,
|
||||
fonts: &Assets<Font>,
|
||||
) -> FontFaceInfo {
|
||||
let font_handle = style.font.clone();
|
||||
let font_handle = text_font.font.clone();
|
||||
let (face_id, family_name) = map_handle_to_font_id
|
||||
.entry(font_handle.id())
|
||||
.or_insert_with(|| {
|
||||
|
@ -461,10 +468,11 @@ fn load_font_to_fontdb(
|
|||
}
|
||||
}
|
||||
|
||||
/// Translates [`TextStyle`] to [`Attrs`].
|
||||
/// Translates [`TextFont`] to [`Attrs`].
|
||||
fn get_attrs<'a>(
|
||||
span_index: usize,
|
||||
style: &TextStyle,
|
||||
text_font: &TextFont,
|
||||
color: Color,
|
||||
face_info: &'a FontFaceInfo,
|
||||
scale_factor: f64,
|
||||
) -> Attrs<'a> {
|
||||
|
@ -474,8 +482,8 @@ fn get_attrs<'a>(
|
|||
.stretch(face_info.stretch)
|
||||
.style(face_info.style)
|
||||
.weight(face_info.weight)
|
||||
.metrics(Metrics::relative(style.font_size, 1.2).scale(scale_factor as f32))
|
||||
.color(cosmic_text::Color(style.color.to_linear().as_u32()));
|
||||
.metrics(Metrics::relative(text_font.font_size, 1.2).scale(scale_factor as f32))
|
||||
.color(cosmic_text::Color(color.to_linear().as_u32()));
|
||||
attrs
|
||||
}
|
||||
|
||||
|
|
|
@ -58,11 +58,11 @@ pub struct ComputedTextBlock {
|
|||
///
|
||||
/// Includes:
|
||||
/// - [`TextLayout`] changes.
|
||||
/// - [`TextStyle`] or `Text2d`/`Text`/`TextSpan` changes anywhere in the block's entity hierarchy.
|
||||
/// - [`TextFont`] or `Text2d`/`Text`/`TextSpan` changes anywhere in the block's entity hierarchy.
|
||||
// TODO: This encompasses both structural changes like font size or justification and non-structural
|
||||
// changes like text color and font smoothing. This field currently causes UI to 'remeasure' text, even if
|
||||
// the actual changes are non-structural and can be handled by only rerendering and not remeasuring. A full
|
||||
// solution would probably require splitting TextLayout and TextStyle into structural/non-structural
|
||||
// solution would probably require splitting TextLayout and TextFont into structural/non-structural
|
||||
// components for more granular change detection. A cost/benefit analysis is needed.
|
||||
pub(crate) needs_rerender: bool,
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ pub struct ComputedTextBlock {
|
|||
impl ComputedTextBlock {
|
||||
/// Accesses entities in this block.
|
||||
///
|
||||
/// Can be used to look up [`TextStyle`] components for glyphs in [`TextLayoutInfo`] using the `span_index`
|
||||
/// Can be used to look up [`TextFont`] components for glyphs in [`TextLayoutInfo`] using the `span_index`
|
||||
/// stored there.
|
||||
pub fn entities(&self) -> &[TextEntity] {
|
||||
&self.entities
|
||||
|
@ -97,7 +97,7 @@ impl Default for ComputedTextBlock {
|
|||
|
||||
/// Component with text format settings for a block of text.
|
||||
///
|
||||
/// A block of text is composed of text spans, which each have a separate string value and [`TextStyle`]. Text
|
||||
/// A block of text is composed of text spans, which each have a separate string value and [`TextFont`]. Text
|
||||
/// spans associated with a text block are collected into [`ComputedTextBlock`] for layout, and then inserted
|
||||
/// to [`TextLayoutInfo`] for rendering.
|
||||
///
|
||||
|
@ -159,38 +159,39 @@ impl TextLayout {
|
|||
///
|
||||
/// Spans are collected in hierarchy traversal order into a [`ComputedTextBlock`] for layout.
|
||||
///
|
||||
/*
|
||||
```
|
||||
# use bevy_asset::Handle;
|
||||
# use bevy_color::Color;
|
||||
# use bevy_color::palettes::basic::{RED, BLUE};
|
||||
# use bevy_ecs::World;
|
||||
# use bevy_text::{Font, TextLayout, TextStyle, TextSection};
|
||||
|
||||
# let font_handle: Handle<Font> = Default::default();
|
||||
# let mut world = World::default();
|
||||
#
|
||||
world.spawn((
|
||||
TextLayout::default(),
|
||||
TextStyle {
|
||||
font: font_handle.clone().into(),
|
||||
font_size: 60.0,
|
||||
color: BLUE.into(),
|
||||
}
|
||||
))
|
||||
.with_child((
|
||||
TextSpan::new("Hello!"),
|
||||
TextStyle {
|
||||
font: font_handle.into(),
|
||||
font_size: 60.0,
|
||||
color: RED.into(),
|
||||
}
|
||||
));
|
||||
```
|
||||
*/
|
||||
/// ```
|
||||
/// # use bevy_asset::Handle;
|
||||
/// # use bevy_color::Color;
|
||||
/// # use bevy_color::palettes::basic::{RED, BLUE};
|
||||
/// # use bevy_ecs::world::World;
|
||||
/// # use bevy_text::{Font, TextLayout, TextFont, TextSpan, TextColor};
|
||||
/// # use bevy_hierarchy::BuildChildren;
|
||||
///
|
||||
/// # let font_handle: Handle<Font> = Default::default();
|
||||
/// # let mut world = World::default();
|
||||
/// #
|
||||
/// world.spawn((
|
||||
/// TextLayout::default(),
|
||||
/// TextFont {
|
||||
/// font: font_handle.clone().into(),
|
||||
/// font_size: 60.0,
|
||||
/// ..Default::default()
|
||||
/// },
|
||||
/// TextColor(BLUE.into()),
|
||||
/// ))
|
||||
/// .with_child((
|
||||
/// TextSpan::new("Hello!"),
|
||||
/// TextFont {
|
||||
/// font: font_handle.into(),
|
||||
/// font_size: 60.0,
|
||||
/// ..Default::default()
|
||||
/// },
|
||||
/// TextColor(RED.into()),
|
||||
/// ));
|
||||
/// ```
|
||||
#[derive(Component, Debug, Default, Clone, Deref, DerefMut, Reflect)]
|
||||
#[reflect(Component, Default, Debug)]
|
||||
#[require(TextStyle)]
|
||||
#[require(TextFont, TextColor)]
|
||||
pub struct TextSpan(pub String);
|
||||
|
||||
impl TextSpan {
|
||||
|
@ -259,11 +260,11 @@ impl From<JustifyText> for cosmic_text::Align {
|
|||
}
|
||||
}
|
||||
|
||||
/// `TextStyle` determines the style of a text span within a [`ComputedTextBlock`], specifically
|
||||
/// `TextFont` determines the style of a text span within a [`ComputedTextBlock`], specifically
|
||||
/// the font face, the font size, and the color.
|
||||
#[derive(Component, Clone, Debug, Reflect)]
|
||||
#[reflect(Component, Default, Debug)]
|
||||
pub struct TextStyle {
|
||||
pub struct TextFont {
|
||||
/// The specific font face to use, as a `Handle` to a [`Font`] asset.
|
||||
///
|
||||
/// If the `font` is not specified, then
|
||||
|
@ -280,31 +281,52 @@ pub struct TextStyle {
|
|||
/// A new font atlas is generated for every combination of font handle and scaled font size
|
||||
/// which can have a strong performance impact.
|
||||
pub font_size: f32,
|
||||
/// The color of the text for this section.
|
||||
pub color: Color,
|
||||
/// The antialiasing method to use when rendering text.
|
||||
pub font_smoothing: FontSmoothing,
|
||||
}
|
||||
|
||||
impl TextStyle {
|
||||
/// Returns this [`TextStyle`] with the specified [`FontSmoothing`].
|
||||
impl TextFont {
|
||||
/// Returns this [`TextFont`] with the specified [`FontSmoothing`].
|
||||
pub const fn with_font_smoothing(mut self, font_smoothing: FontSmoothing) -> Self {
|
||||
self.font_smoothing = font_smoothing;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TextStyle {
|
||||
impl Default for TextFont {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
font: Default::default(),
|
||||
font_size: 20.0,
|
||||
color: Color::WHITE,
|
||||
font_smoothing: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The color of the text for this section.
|
||||
#[derive(Component, Copy, Clone, Debug, Deref, DerefMut, Reflect)]
|
||||
#[reflect(Component, Default, Debug)]
|
||||
pub struct TextColor(pub Color);
|
||||
|
||||
impl Default for TextColor {
|
||||
fn default() -> Self {
|
||||
Self::WHITE
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<Color>> From<T> for TextColor {
|
||||
fn from(color: T) -> Self {
|
||||
Self(color.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl TextColor {
|
||||
/// Black colored text
|
||||
pub const BLACK: Self = TextColor(Color::BLACK);
|
||||
/// White colored text
|
||||
pub const WHITE: Self = TextColor(Color::WHITE);
|
||||
}
|
||||
|
||||
/// Determines how lines will be broken when preventing text from running out of bounds.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Reflect, Serialize, Deserialize)]
|
||||
#[reflect(Serialize, Deserialize)]
|
||||
|
@ -359,12 +381,12 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
|||
(
|
||||
Or<(
|
||||
Changed<Root>,
|
||||
Changed<TextStyle>,
|
||||
Changed<TextFont>,
|
||||
Changed<TextLayout>,
|
||||
Changed<Children>,
|
||||
)>,
|
||||
With<Root>,
|
||||
With<TextStyle>,
|
||||
With<TextFont>,
|
||||
With<TextLayout>,
|
||||
),
|
||||
>,
|
||||
|
@ -373,13 +395,13 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
|||
(
|
||||
Or<(
|
||||
Changed<TextSpan>,
|
||||
Changed<TextStyle>,
|
||||
Changed<TextFont>,
|
||||
Changed<Children>,
|
||||
Changed<Parent>, // Included to detect broken text block hierarchies.
|
||||
Added<TextLayout>,
|
||||
)>,
|
||||
With<TextSpan>,
|
||||
With<TextStyle>,
|
||||
With<TextFont>,
|
||||
),
|
||||
>,
|
||||
mut computed: Query<(
|
||||
|
@ -390,7 +412,7 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
|||
) {
|
||||
// Root entity:
|
||||
// - Root component changed.
|
||||
// - TextStyle on root changed.
|
||||
// - TextFont on root changed.
|
||||
// - TextLayout changed.
|
||||
// - Root children changed (can include additions and removals).
|
||||
for root in changed_roots.iter() {
|
||||
|
@ -404,7 +426,7 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
|||
|
||||
// Span entity:
|
||||
// - Span component changed.
|
||||
// - Span TextStyle changed.
|
||||
// - Span TextFont changed.
|
||||
// - Span children changed (can include additions and removals).
|
||||
for (entity, maybe_span_parent, has_text_block) in changed_spans.iter() {
|
||||
if has_text_block {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::pipeline::CosmicFontSystem;
|
||||
use crate::{
|
||||
ComputedTextBlock, Font, FontAtlasSets, LineBreak, PositionedGlyph, SwashCache, TextBounds,
|
||||
TextError, TextLayout, TextLayoutInfo, TextPipeline, TextReader, TextRoot, TextSpanAccess,
|
||||
TextStyle, TextWriter, YAxisOrientation,
|
||||
TextColor, TextError, TextFont, TextLayout, TextLayoutInfo, TextPipeline, TextReader, TextRoot,
|
||||
TextSpanAccess, TextWriter, YAxisOrientation,
|
||||
};
|
||||
use bevy_asset::Assets;
|
||||
use bevy_color::LinearRgba;
|
||||
|
@ -44,42 +44,43 @@ use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged};
|
|||
/// relative position, which is controlled by the [`Anchor`] component.
|
||||
/// This means that for a block of text consisting of only one line that doesn't wrap, the `justify` field will have no effect.
|
||||
///
|
||||
/*
|
||||
```
|
||||
# use bevy_asset::Handle;
|
||||
# use bevy_color::Color;
|
||||
# use bevy_color::palettes::basic::BLUE;
|
||||
# use bevy_ecs::World;
|
||||
# use bevy_text::{Font, JustifyText, Text2d, TextLayout, TextStyle};
|
||||
#
|
||||
# let font_handle: Handle<Font> = Default::default();
|
||||
# let mut world = World::default();
|
||||
#
|
||||
// Basic usage.
|
||||
world.spawn(Text2d::new("hello world!"));
|
||||
|
||||
// With non-default style.
|
||||
world.spawn((
|
||||
Text2d::new("hello world!"),
|
||||
TextStyle {
|
||||
font: font_handle.clone().into(),
|
||||
font_size: 60.0,
|
||||
color: BLUE.into(),
|
||||
}
|
||||
));
|
||||
|
||||
// With text justification.
|
||||
world.spawn((
|
||||
Text2d::new("hello world\nand bevy!"),
|
||||
TextLayout::new_with_justify(JustifyText::Center)
|
||||
));
|
||||
```
|
||||
*/
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_asset::Handle;
|
||||
/// # use bevy_color::Color;
|
||||
/// # use bevy_color::palettes::basic::BLUE;
|
||||
/// # use bevy_ecs::world::World;
|
||||
/// # use bevy_text::{Font, JustifyText, Text2d, TextLayout, TextFont, TextColor};
|
||||
/// #
|
||||
/// # let font_handle: Handle<Font> = Default::default();
|
||||
/// # let mut world = World::default();
|
||||
/// #
|
||||
/// // Basic usage.
|
||||
/// world.spawn(Text2d::new("hello world!"));
|
||||
///
|
||||
/// // With non-default style.
|
||||
/// world.spawn((
|
||||
/// Text2d::new("hello world!"),
|
||||
/// TextFont {
|
||||
/// font: font_handle.clone().into(),
|
||||
/// font_size: 60.0,
|
||||
/// ..Default::default()
|
||||
/// },
|
||||
/// TextColor(BLUE.into()),
|
||||
/// ));
|
||||
///
|
||||
/// // With text justification.
|
||||
/// world.spawn((
|
||||
/// Text2d::new("hello world\nand bevy!"),
|
||||
/// TextLayout::new_with_justify(JustifyText::Center)
|
||||
/// ));
|
||||
/// ```
|
||||
#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect)]
|
||||
#[reflect(Component, Default, Debug)]
|
||||
#[require(
|
||||
TextLayout,
|
||||
TextStyle,
|
||||
TextFont,
|
||||
TextColor,
|
||||
TextBounds,
|
||||
Anchor,
|
||||
SpriteSource,
|
||||
|
@ -141,7 +142,7 @@ pub fn extract_text2d_sprite(
|
|||
&GlobalTransform,
|
||||
)>,
|
||||
>,
|
||||
text_styles: Extract<Query<&TextStyle>>,
|
||||
text_styles: Extract<Query<(&TextFont, &TextColor)>>,
|
||||
) {
|
||||
// TODO: Support window-independent scaling: https://github.com/bevyengine/bevy/issues/5621
|
||||
let scale_factor = windows
|
||||
|
@ -186,7 +187,7 @@ pub fn extract_text2d_sprite(
|
|||
.map(|t| t.entity)
|
||||
.unwrap_or(Entity::PLACEHOLDER),
|
||||
)
|
||||
.map(|style| LinearRgba::from(style.color))
|
||||
.map(|(_, text_color)| LinearRgba::from(text_color.0))
|
||||
.unwrap_or_default();
|
||||
current_span = *span_index;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use bevy_color::Color;
|
||||
use bevy_ecs::{
|
||||
prelude::*,
|
||||
system::{Query, SystemParam},
|
||||
};
|
||||
use bevy_hierarchy::Children;
|
||||
|
||||
use crate::{TextSpan, TextStyle};
|
||||
use crate::{TextColor, TextFont, TextSpan};
|
||||
|
||||
/// Helper trait for using the [`TextReader`] and [`TextWriter`] system params.
|
||||
pub trait TextSpanAccess: Component {
|
||||
|
@ -49,13 +50,23 @@ impl TextIterScratch {
|
|||
pub struct TextReader<'w, 's, R: TextRoot> {
|
||||
// This is a local to avoid system ambiguities when TextReaders run in parallel.
|
||||
scratch: Local<'s, TextIterScratch>,
|
||||
roots: Query<'w, 's, (&'static R, &'static TextStyle, Option<&'static Children>)>,
|
||||
roots: Query<
|
||||
'w,
|
||||
's,
|
||||
(
|
||||
&'static R,
|
||||
&'static TextFont,
|
||||
&'static TextColor,
|
||||
Option<&'static Children>,
|
||||
),
|
||||
>,
|
||||
spans: Query<
|
||||
'w,
|
||||
's,
|
||||
(
|
||||
&'static TextSpan,
|
||||
&'static TextStyle,
|
||||
&'static TextFont,
|
||||
&'static TextColor,
|
||||
Option<&'static Children>,
|
||||
),
|
||||
>,
|
||||
|
@ -80,18 +91,24 @@ impl<'w, 's, R: TextRoot> TextReader<'w, 's, R> {
|
|||
&mut self,
|
||||
root_entity: Entity,
|
||||
index: usize,
|
||||
) -> Option<(Entity, usize, &str, &TextStyle)> {
|
||||
) -> Option<(Entity, usize, &str, &TextFont, Color)> {
|
||||
self.iter(root_entity).nth(index)
|
||||
}
|
||||
|
||||
/// Gets the text value of a text span within a text block at a specific index in the flattened span list.
|
||||
pub fn get_text(&mut self, root_entity: Entity, index: usize) -> Option<&str> {
|
||||
self.get(root_entity, index).map(|(_, _, text, _)| text)
|
||||
self.get(root_entity, index).map(|(_, _, text, _, _)| text)
|
||||
}
|
||||
|
||||
/// Gets the [`TextStyle`] of a text span within a text block at a specific index in the flattened span list.
|
||||
pub fn get_style(&mut self, root_entity: Entity, index: usize) -> Option<&TextStyle> {
|
||||
self.get(root_entity, index).map(|(_, _, _, style)| style)
|
||||
/// Gets the [`TextFont`] of a text span within a text block at a specific index in the flattened span list.
|
||||
pub fn get_font(&mut self, root_entity: Entity, index: usize) -> Option<&TextFont> {
|
||||
self.get(root_entity, index).map(|(_, _, _, font, _)| font)
|
||||
}
|
||||
|
||||
/// Gets the [`TextColor`] of a text span within a text block at a specific index in the flattened span list.
|
||||
pub fn get_color(&mut self, root_entity: Entity, index: usize) -> Option<Color> {
|
||||
self.get(root_entity, index)
|
||||
.map(|(_, _, _, _, color)| color)
|
||||
}
|
||||
|
||||
/// Gets the text value of a text span within a text block at a specific index in the flattened span list.
|
||||
|
@ -101,11 +118,18 @@ impl<'w, 's, R: TextRoot> TextReader<'w, 's, R> {
|
|||
self.get_text(root_entity, index).unwrap()
|
||||
}
|
||||
|
||||
/// Gets the [`TextStyle`] of a text span within a text block at a specific index in the flattened span list.
|
||||
/// Gets the [`TextFont`] of a text span within a text block at a specific index in the flattened span list.
|
||||
///
|
||||
/// Panics if there is no span at the requested index.
|
||||
pub fn style(&mut self, root_entity: Entity, index: usize) -> &TextStyle {
|
||||
self.get_style(root_entity, index).unwrap()
|
||||
pub fn font(&mut self, root_entity: Entity, index: usize) -> &TextFont {
|
||||
self.get_font(root_entity, index).unwrap()
|
||||
}
|
||||
|
||||
/// Gets the [`TextColor`] of a text span within a text block at a specific index in the flattened span list.
|
||||
///
|
||||
/// Panics if there is no span at the requested index.
|
||||
pub fn color(&mut self, root_entity: Entity, index: usize) -> Color {
|
||||
self.get_color(root_entity, index).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,13 +143,23 @@ pub struct TextSpanIter<'a, R: TextRoot> {
|
|||
root_entity: Option<Entity>,
|
||||
/// Stack of (children, next index into children).
|
||||
stack: Vec<(&'a Children, usize)>,
|
||||
roots: &'a Query<'a, 'a, (&'static R, &'static TextStyle, Option<&'static Children>)>,
|
||||
roots: &'a Query<
|
||||
'a,
|
||||
'a,
|
||||
(
|
||||
&'static R,
|
||||
&'static TextFont,
|
||||
&'static TextColor,
|
||||
Option<&'static Children>,
|
||||
),
|
||||
>,
|
||||
spans: &'a Query<
|
||||
'a,
|
||||
'a,
|
||||
(
|
||||
&'static TextSpan,
|
||||
&'static TextStyle,
|
||||
&'static TextFont,
|
||||
&'static TextColor,
|
||||
Option<&'static Children>,
|
||||
),
|
||||
>,
|
||||
|
@ -133,15 +167,15 @@ pub struct TextSpanIter<'a, R: TextRoot> {
|
|||
|
||||
impl<'a, R: TextRoot> Iterator for TextSpanIter<'a, R> {
|
||||
/// Item = (entity in text block, hierarchy depth in the block, span text, span style).
|
||||
type Item = (Entity, usize, &'a str, &'a TextStyle);
|
||||
type Item = (Entity, usize, &'a str, &'a TextFont, Color);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// Root
|
||||
if let Some(root_entity) = self.root_entity.take() {
|
||||
if let Ok((text, style, maybe_children)) = self.roots.get(root_entity) {
|
||||
if let Ok((text, style, color, maybe_children)) = self.roots.get(root_entity) {
|
||||
if let Some(children) = maybe_children {
|
||||
self.stack.push((children, 0));
|
||||
}
|
||||
return Some((root_entity, 0, text.read_span(), style));
|
||||
return Some((root_entity, 0, text.read_span(), style, color.0));
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
@ -159,7 +193,7 @@ impl<'a, R: TextRoot> Iterator for TextSpanIter<'a, R> {
|
|||
*idx += 1;
|
||||
|
||||
let entity = *child;
|
||||
let Ok((span, style, maybe_children)) = self.spans.get(entity) else {
|
||||
let Ok((span, style, color, maybe_children)) = self.spans.get(entity) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
@ -167,7 +201,7 @@ impl<'a, R: TextRoot> Iterator for TextSpanIter<'a, R> {
|
|||
if let Some(children) = maybe_children {
|
||||
self.stack.push((children, 0));
|
||||
}
|
||||
return Some((entity, depth, span.read_span(), style));
|
||||
return Some((entity, depth, span.read_span(), style, color.0));
|
||||
}
|
||||
|
||||
// All children at this stack entry have been iterated.
|
||||
|
@ -191,8 +225,26 @@ impl<'a, R: TextRoot> Drop for TextSpanIter<'a, R> {
|
|||
pub struct TextWriter<'w, 's, R: TextRoot> {
|
||||
// This is a resource because two TextWriters can't run in parallel.
|
||||
scratch: ResMut<'w, TextIterScratch>,
|
||||
roots: Query<'w, 's, (&'static mut R, &'static mut TextStyle), Without<TextSpan>>,
|
||||
spans: Query<'w, 's, (&'static mut TextSpan, &'static mut TextStyle), Without<R>>,
|
||||
roots: Query<
|
||||
'w,
|
||||
's,
|
||||
(
|
||||
&'static mut R,
|
||||
&'static mut TextFont,
|
||||
&'static mut TextColor,
|
||||
),
|
||||
Without<TextSpan>,
|
||||
>,
|
||||
spans: Query<
|
||||
'w,
|
||||
's,
|
||||
(
|
||||
&'static mut TextSpan,
|
||||
&'static mut TextFont,
|
||||
&'static mut TextColor,
|
||||
),
|
||||
Without<R>,
|
||||
>,
|
||||
children: Query<'w, 's, &'static Children>,
|
||||
}
|
||||
|
||||
|
@ -202,15 +254,16 @@ impl<'w, 's, R: TextRoot> TextWriter<'w, 's, R> {
|
|||
&mut self,
|
||||
root_entity: Entity,
|
||||
index: usize,
|
||||
) -> Option<(Entity, usize, Mut<String>, Mut<TextStyle>)> {
|
||||
) -> Option<(Entity, usize, Mut<String>, Mut<TextFont>, Mut<TextColor>)> {
|
||||
// Root
|
||||
if index == 0 {
|
||||
let (text, style) = self.roots.get_mut(root_entity).ok()?;
|
||||
let (text, font, color) = self.roots.get_mut(root_entity).ok()?;
|
||||
return Some((
|
||||
root_entity,
|
||||
0,
|
||||
text.map_unchanged(|t| t.write_span()),
|
||||
style,
|
||||
font,
|
||||
color,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -257,18 +310,30 @@ impl<'w, 's, R: TextRoot> TextWriter<'w, 's, R> {
|
|||
};
|
||||
|
||||
// Note: We do this outside the loop due to borrow checker limitations.
|
||||
let (text, style) = self.spans.get_mut(entity).unwrap();
|
||||
Some((entity, depth, text.map_unchanged(|t| t.write_span()), style))
|
||||
let (text, font, color) = self.spans.get_mut(entity).unwrap();
|
||||
Some((
|
||||
entity,
|
||||
depth,
|
||||
text.map_unchanged(|t| t.write_span()),
|
||||
font,
|
||||
color,
|
||||
))
|
||||
}
|
||||
|
||||
/// Gets the text value of a text span within a text block at a specific index in the flattened span list.
|
||||
pub fn get_text(&mut self, root_entity: Entity, index: usize) -> Option<Mut<String>> {
|
||||
self.get(root_entity, index).map(|(_, _, text, _)| text)
|
||||
self.get(root_entity, index).map(|(_, _, text, ..)| text)
|
||||
}
|
||||
|
||||
/// Gets the [`TextStyle`] of a text span within a text block at a specific index in the flattened span list.
|
||||
pub fn get_style(&mut self, root_entity: Entity, index: usize) -> Option<Mut<TextStyle>> {
|
||||
self.get(root_entity, index).map(|(_, _, _, style)| style)
|
||||
/// Gets the [`TextFont`] of a text span within a text block at a specific index in the flattened span list.
|
||||
pub fn get_font(&mut self, root_entity: Entity, index: usize) -> Option<Mut<TextFont>> {
|
||||
self.get(root_entity, index).map(|(_, _, _, font, _)| font)
|
||||
}
|
||||
|
||||
/// Gets the [`TextColor`] of a text span within a text block at a specific index in the flattened span list.
|
||||
pub fn get_color(&mut self, root_entity: Entity, index: usize) -> Option<Mut<TextColor>> {
|
||||
self.get(root_entity, index)
|
||||
.map(|(_, _, _, _, color)| color)
|
||||
}
|
||||
|
||||
/// Gets the text value of a text span within a text block at a specific index in the flattened span list.
|
||||
|
@ -278,40 +343,54 @@ impl<'w, 's, R: TextRoot> TextWriter<'w, 's, R> {
|
|||
self.get_text(root_entity, index).unwrap()
|
||||
}
|
||||
|
||||
/// Gets the [`TextStyle`] of a text span within a text block at a specific index in the flattened span list.
|
||||
/// Gets the [`TextFont`] of a text span within a text block at a specific index in the flattened span list.
|
||||
///
|
||||
/// Panics if there is no span at the requested index.
|
||||
pub fn style(&mut self, root_entity: Entity, index: usize) -> Mut<TextStyle> {
|
||||
self.get_style(root_entity, index).unwrap()
|
||||
pub fn font(&mut self, root_entity: Entity, index: usize) -> Mut<TextFont> {
|
||||
self.get_font(root_entity, index).unwrap()
|
||||
}
|
||||
|
||||
/// Gets the [`TextColor`] of a text span within a text block at a specific index in the flattened span list.
|
||||
///
|
||||
/// Panics if there is no span at the requested index.
|
||||
pub fn color(&mut self, root_entity: Entity, index: usize) -> Mut<TextColor> {
|
||||
self.get_color(root_entity, index).unwrap()
|
||||
}
|
||||
|
||||
/// Invokes a callback on each span in a text block, starting with the root entity.
|
||||
pub fn for_each(
|
||||
&mut self,
|
||||
root_entity: Entity,
|
||||
mut callback: impl FnMut(Entity, usize, Mut<String>, Mut<TextStyle>),
|
||||
mut callback: impl FnMut(Entity, usize, Mut<String>, Mut<TextFont>, Mut<TextColor>),
|
||||
) {
|
||||
self.for_each_until(root_entity, |a, b, c, d| {
|
||||
(callback)(a, b, c, d);
|
||||
self.for_each_until(root_entity, |a, b, c, d, e| {
|
||||
(callback)(a, b, c, d, e);
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
/// Invokes a callback on each span's string value in a text block, starting with the root entity.
|
||||
pub fn for_each_text(&mut self, root_entity: Entity, mut callback: impl FnMut(Mut<String>)) {
|
||||
self.for_each(root_entity, |_, _, text, _| {
|
||||
self.for_each(root_entity, |_, _, text, _, _| {
|
||||
(callback)(text);
|
||||
});
|
||||
}
|
||||
|
||||
/// Invokes a callback on each span's [`TextStyle`] in a text block, starting with the root entity.
|
||||
pub fn for_each_style(
|
||||
/// Invokes a callback on each span's [`TextFont`] in a text block, starting with the root entity.
|
||||
pub fn for_each_font(&mut self, root_entity: Entity, mut callback: impl FnMut(Mut<TextFont>)) {
|
||||
self.for_each(root_entity, |_, _, _, font, _| {
|
||||
(callback)(font);
|
||||
});
|
||||
}
|
||||
|
||||
/// Invokes a callback on each span's [`TextColor`] in a text block, starting with the root entity.
|
||||
pub fn for_each_color(
|
||||
&mut self,
|
||||
root_entity: Entity,
|
||||
mut callback: impl FnMut(Mut<TextStyle>),
|
||||
mut callback: impl FnMut(Mut<TextColor>),
|
||||
) {
|
||||
self.for_each(root_entity, |_, _, _, style| {
|
||||
(callback)(style);
|
||||
self.for_each(root_entity, |_, _, _, _, color| {
|
||||
(callback)(color);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -322,17 +401,18 @@ impl<'w, 's, R: TextRoot> TextWriter<'w, 's, R> {
|
|||
pub fn for_each_until(
|
||||
&mut self,
|
||||
root_entity: Entity,
|
||||
mut callback: impl FnMut(Entity, usize, Mut<String>, Mut<TextStyle>) -> bool,
|
||||
mut callback: impl FnMut(Entity, usize, Mut<String>, Mut<TextFont>, Mut<TextColor>) -> bool,
|
||||
) {
|
||||
// Root
|
||||
let Ok((text, style)) = self.roots.get_mut(root_entity) else {
|
||||
let Ok((text, font, color)) = self.roots.get_mut(root_entity) else {
|
||||
return;
|
||||
};
|
||||
if !(callback)(
|
||||
root_entity,
|
||||
0,
|
||||
text.map_unchanged(|t| t.write_span()),
|
||||
style,
|
||||
font,
|
||||
color,
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -362,11 +442,17 @@ impl<'w, 's, R: TextRoot> TextWriter<'w, 's, R> {
|
|||
*idx += 1;
|
||||
|
||||
let entity = *child;
|
||||
let Ok((text, style)) = self.spans.get_mut(entity) else {
|
||||
let Ok((text, font, color)) = self.spans.get_mut(entity) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if !(callback)(entity, depth, text.map_unchanged(|t| t.write_span()), style) {
|
||||
if !(callback)(
|
||||
entity,
|
||||
depth,
|
||||
text.map_unchanged(|t| t.write_span()),
|
||||
font,
|
||||
color,
|
||||
) {
|
||||
self.scratch.recover(stack);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ fn calc_name(
|
|||
for child in children {
|
||||
let values = text_reader
|
||||
.iter(child)
|
||||
.map(|(_, _, text, _)| text.into())
|
||||
.map(|(_, _, text, _, _)| text.into())
|
||||
.collect::<Vec<String>>();
|
||||
if !values.is_empty() {
|
||||
name = Some(values.join(" "));
|
||||
|
@ -120,7 +120,7 @@ fn label_changed(
|
|||
for (entity, accessible) in &mut query {
|
||||
let values = text_reader
|
||||
.iter(entity)
|
||||
.map(|(_, _, text, _)| text.into())
|
||||
.map(|(_, _, text, _, _)| text.into())
|
||||
.collect::<Vec<String>>();
|
||||
let name = Some(values.join(" ").into_boxed_str());
|
||||
if let Some(mut accessible) = accessible {
|
||||
|
|
|
@ -41,7 +41,7 @@ use bevy_render::{
|
|||
use bevy_sprite::TextureAtlasLayout;
|
||||
use bevy_sprite::{BorderRect, ImageScaleMode, SpriteAssetEvents, TextureAtlas};
|
||||
#[cfg(feature = "bevy_text")]
|
||||
use bevy_text::{ComputedTextBlock, PositionedGlyph, TextLayoutInfo, TextStyle};
|
||||
use bevy_text::{ComputedTextBlock, PositionedGlyph, TextColor, TextLayoutInfo};
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use bevy_utils::HashMap;
|
||||
use box_shadow::BoxShadowPlugin;
|
||||
|
@ -606,7 +606,7 @@ pub fn extract_text_sections(
|
|||
&TextLayoutInfo,
|
||||
)>,
|
||||
>,
|
||||
text_styles: Extract<Query<&TextStyle>>,
|
||||
text_styles: Extract<Query<&TextColor>>,
|
||||
mapping: Extract<Query<&RenderEntity>>,
|
||||
) {
|
||||
let mut start = 0;
|
||||
|
@ -681,7 +681,7 @@ pub fn extract_text_sections(
|
|||
.map(|t| t.entity)
|
||||
.unwrap_or(Entity::PLACEHOLDER),
|
||||
)
|
||||
.map(|style| LinearRgba::from(style.color))
|
||||
.map(|text_color| LinearRgba::from(text_color.0))
|
||||
.unwrap_or_default();
|
||||
current_span = *span_index;
|
||||
}
|
||||
|
|
|
@ -2520,7 +2520,7 @@ impl<'w, 's> DefaultUiCamera<'w, 's> {
|
|||
/// Marker for controlling whether Ui is rendered with or without anti-aliasing
|
||||
/// in a camera. By default, Ui is always anti-aliased.
|
||||
///
|
||||
/// **Note:** This does not affect text anti-aliasing. For that, use the `font_smoothing` property of the [`TextStyle`](bevy_text::TextStyle) component.
|
||||
/// **Note:** This does not affect text anti-aliasing. For that, use the `font_smoothing` property of the [`TextFont`](bevy_text::TextFont) component.
|
||||
///
|
||||
/// ```
|
||||
/// use bevy_core_pipeline::prelude::*;
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::{
|
|||
NodeMeasure, Style, TargetCamera, UiScale, ZIndex,
|
||||
};
|
||||
use bevy_asset::Assets;
|
||||
use bevy_color::Color;
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_ecs::{
|
||||
change_detection::DetectChanges,
|
||||
|
@ -19,8 +20,8 @@ use bevy_render::{camera::Camera, texture::Image, view::Visibility};
|
|||
use bevy_sprite::TextureAtlasLayout;
|
||||
use bevy_text::{
|
||||
scale_value, ComputedTextBlock, CosmicFontSystem, Font, FontAtlasSets, LineBreak, SwashCache,
|
||||
TextBounds, TextError, TextLayout, TextLayoutInfo, TextMeasureInfo, TextPipeline, TextReader,
|
||||
TextRoot, TextSpanAccess, TextStyle, TextWriter, YAxisOrientation,
|
||||
TextBounds, TextColor, TextError, TextFont, TextLayout, TextLayoutInfo, TextMeasureInfo,
|
||||
TextPipeline, TextReader, TextRoot, TextSpanAccess, TextWriter, YAxisOrientation,
|
||||
};
|
||||
use bevy_transform::components::Transform;
|
||||
use bevy_utils::{tracing::error, Entry};
|
||||
|
@ -56,43 +57,44 @@ impl Default for TextNodeFlags {
|
|||
///
|
||||
/// Note that [`Transform`] on this entity is managed automatically by the UI layout system.
|
||||
///
|
||||
/*
|
||||
```
|
||||
# use bevy_asset::Handle;
|
||||
# use bevy_color::Color;
|
||||
# use bevy_color::palettes::basic::BLUE;
|
||||
# use bevy_ecs::World;
|
||||
# use bevy_text::{Font, JustifyText, TextLayout, TextStyle};
|
||||
# use bevy_ui::Text;
|
||||
#
|
||||
# let font_handle: Handle<Font> = Default::default();
|
||||
# let mut world = World::default();
|
||||
#
|
||||
// Basic usage.
|
||||
world.spawn(Text::new("hello world!"));
|
||||
|
||||
// With non-default style.
|
||||
world.spawn((
|
||||
Text::new("hello world!"),
|
||||
TextStyle {
|
||||
font: font_handle.clone().into(),
|
||||
font_size: 60.0,
|
||||
color: BLUE.into(),
|
||||
}
|
||||
));
|
||||
|
||||
// With text justification.
|
||||
world.spawn((
|
||||
Text::new("hello world\nand bevy!"),
|
||||
TextLayout::new_with_justify(JustifyText::Center)
|
||||
));
|
||||
```
|
||||
*/
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_asset::Handle;
|
||||
/// # use bevy_color::Color;
|
||||
/// # use bevy_color::palettes::basic::BLUE;
|
||||
/// # use bevy_ecs::world::World;
|
||||
/// # use bevy_text::{Font, JustifyText, TextLayout, TextFont, TextColor};
|
||||
/// # use bevy_ui::prelude::Text;
|
||||
/// #
|
||||
/// # let font_handle: Handle<Font> = Default::default();
|
||||
/// # let mut world = World::default();
|
||||
/// #
|
||||
/// // Basic usage.
|
||||
/// world.spawn(Text::new("hello world!"));
|
||||
///
|
||||
/// // With non-default style.
|
||||
/// world.spawn((
|
||||
/// Text::new("hello world!"),
|
||||
/// TextFont {
|
||||
/// font: font_handle.clone().into(),
|
||||
/// font_size: 60.0,
|
||||
/// ..Default::default()
|
||||
/// },
|
||||
/// TextColor(BLUE.into()),
|
||||
/// ));
|
||||
///
|
||||
/// // With text justification.
|
||||
/// world.spawn((
|
||||
/// Text::new("hello world\nand bevy!"),
|
||||
/// TextLayout::new_with_justify(JustifyText::Center)
|
||||
/// ));
|
||||
/// ```
|
||||
#[derive(Component, Debug, Default, Clone, Deref, DerefMut, Reflect)]
|
||||
#[reflect(Component, Default, Debug)]
|
||||
#[require(
|
||||
TextLayout,
|
||||
TextStyle,
|
||||
TextFont,
|
||||
TextColor,
|
||||
TextNodeFlags,
|
||||
Node,
|
||||
Style, // TODO: Remove when Node uses required components.
|
||||
|
@ -204,7 +206,7 @@ fn create_text_measure<'a>(
|
|||
entity: Entity,
|
||||
fonts: &Assets<Font>,
|
||||
scale_factor: f64,
|
||||
spans: impl Iterator<Item = (Entity, usize, &'a str, &'a TextStyle)>,
|
||||
spans: impl Iterator<Item = (Entity, usize, &'a str, &'a TextFont, Color)>,
|
||||
block: Ref<TextLayout>,
|
||||
text_pipeline: &mut TextPipeline,
|
||||
mut content_size: Mut<ContentSize>,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
A runtime warning.
|
||||
|
||||
Separate font atlases are created for each font and font size. This is expensive, and the memory is never reclaimed when e.g. interpolating `TextStyle::font_size` or `UiScale::scale`.
|
||||
Separate font atlases are created for each font and font size. This is expensive, and the memory is never reclaimed when e.g. interpolating `TextFont::font_size` or `UiScale::scale`.
|
||||
|
||||
If you need to smoothly scale font size, use `Transform::scale`.
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ fn spawn_sprites(
|
|||
texture_handle: Handle<Image>,
|
||||
mut position: Vec3,
|
||||
slice_border: f32,
|
||||
style: TextStyle,
|
||||
style: TextFont,
|
||||
gap: f32,
|
||||
) {
|
||||
let cases = [
|
||||
|
@ -100,7 +100,7 @@ fn spawn_sprites(
|
|||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
commands.spawn(Camera2d);
|
||||
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
|
||||
let style = TextStyle {
|
||||
let style = TextFont {
|
||||
font: font.clone(),
|
||||
..default()
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ struct AnimateScale;
|
|||
|
||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
|
||||
let text_style = TextStyle {
|
||||
let text_font = TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 50.0,
|
||||
..default()
|
||||
|
@ -46,27 +46,27 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// Demonstrate changing translation
|
||||
commands.spawn((
|
||||
Text2d::new("translation"),
|
||||
text_style.clone(),
|
||||
text_font.clone(),
|
||||
TextLayout::new_with_justify(text_justification),
|
||||
AnimateTranslation,
|
||||
));
|
||||
// Demonstrate changing rotation
|
||||
commands.spawn((
|
||||
Text2d::new("rotation"),
|
||||
text_style.clone(),
|
||||
text_font.clone(),
|
||||
TextLayout::new_with_justify(text_justification),
|
||||
AnimateRotation,
|
||||
));
|
||||
// Demonstrate changing scale
|
||||
commands.spawn((
|
||||
Text2d::new("scale"),
|
||||
text_style,
|
||||
text_font,
|
||||
TextLayout::new_with_justify(text_justification),
|
||||
Transform::from_translation(Vec3::new(400.0, 0.0, 0.0)),
|
||||
AnimateScale,
|
||||
));
|
||||
// Demonstrate text wrapping
|
||||
let slightly_smaller_text_style = TextStyle {
|
||||
let slightly_smaller_text_font = TextFont {
|
||||
font,
|
||||
font_size: 35.0,
|
||||
..default()
|
||||
|
@ -81,7 +81,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.with_children(|builder| {
|
||||
builder.spawn((
|
||||
Text2d::new("this text wraps in the box\n(Unicode linebreaks)"),
|
||||
slightly_smaller_text_style.clone(),
|
||||
slightly_smaller_text_font.clone(),
|
||||
TextLayout::new(JustifyText::Left, LineBreak::WordBoundary),
|
||||
// Wrap text in the rectangle
|
||||
TextBounds::from(box_size),
|
||||
|
@ -100,7 +100,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.with_children(|builder| {
|
||||
builder.spawn((
|
||||
Text2d::new("this text wraps in the box\n(AnyCharacter linebreaks)"),
|
||||
slightly_smaller_text_style.clone(),
|
||||
slightly_smaller_text_font.clone(),
|
||||
TextLayout::new(JustifyText::Left, LineBreak::AnyCharacter),
|
||||
// Wrap text in the rectangle
|
||||
TextBounds::from(other_box_size),
|
||||
|
@ -112,7 +112,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// Demonstrate font smoothing off
|
||||
commands.spawn((
|
||||
Text2d::new("FontSmoothing::None"),
|
||||
slightly_smaller_text_style
|
||||
slightly_smaller_text_font
|
||||
.clone()
|
||||
.with_font_smoothing(FontSmoothing::None),
|
||||
Transform::from_translation(Vec3::new(-400.0, -250.0, 0.0)),
|
||||
|
@ -126,10 +126,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
] {
|
||||
commands.spawn((
|
||||
Text2d::new(format!(" Anchor::{text_anchor:?} ")),
|
||||
TextStyle {
|
||||
color,
|
||||
..slightly_smaller_text_style.clone()
|
||||
},
|
||||
slightly_smaller_text_font.clone(),
|
||||
TextColor(color),
|
||||
Transform::from_translation(250. * Vec3::Y),
|
||||
text_anchor,
|
||||
));
|
||||
|
|
|
@ -121,7 +121,7 @@ fn setup(
|
|||
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
|
||||
|
||||
// padding label text style
|
||||
let text_style: TextStyle = TextStyle {
|
||||
let text_style: TextFont = TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 42.0,
|
||||
..default()
|
||||
|
@ -184,7 +184,7 @@ fn setup(
|
|||
];
|
||||
|
||||
// label text style
|
||||
let sampling_label_style = TextStyle {
|
||||
let sampling_label_style = TextFont {
|
||||
font,
|
||||
font_size: 25.0,
|
||||
..default()
|
||||
|
@ -275,7 +275,7 @@ fn create_label(
|
|||
commands: &mut Commands,
|
||||
translation: (f32, f32, f32),
|
||||
text: &str,
|
||||
text_style: TextStyle,
|
||||
text_style: TextFont,
|
||||
) {
|
||||
commands.spawn((
|
||||
Text2d::new(text),
|
||||
|
|
|
@ -127,7 +127,7 @@ fn setup(
|
|||
..default()
|
||||
});
|
||||
|
||||
let text_style = TextStyle::default();
|
||||
let text_style = TextFont::default();
|
||||
|
||||
commands.spawn((Text::new("Left / Right - Rotate Camera\nC - Toggle Compensation Curve\nM - Toggle Metering Mask\nV - Visualize Metering Mask"),
|
||||
text_style.clone(), Style {
|
||||
|
|
|
@ -160,18 +160,12 @@ fn setup(
|
|||
// Controls Text
|
||||
|
||||
// We need the full version of this font so we can use box drawing characters.
|
||||
let font = asset_server.load("fonts/FiraMono-Medium.ttf");
|
||||
|
||||
let text_style = TextStyle {
|
||||
font: font.clone(),
|
||||
let text_style = TextFont {
|
||||
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
..default()
|
||||
};
|
||||
|
||||
let label_text_style = TextStyle {
|
||||
font,
|
||||
color: ORANGE.into(),
|
||||
..default()
|
||||
};
|
||||
let label_text_style = (text_style.clone(), TextColor(ORANGE.into()));
|
||||
|
||||
commands.spawn((Text::new("Up / Down — Increase / Decrease Alpha\nLeft / Right — Rotate Camera\nH - Toggle HDR\nSpacebar — Toggle Unlit\nC — Randomize Colors"),
|
||||
text_style.clone(),
|
||||
|
|
|
@ -316,7 +316,7 @@ fn add_help_text(
|
|||
) {
|
||||
commands.spawn((
|
||||
Text::new(create_help_text(currently_selected_option)),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
..default()
|
||||
},
|
||||
|
@ -339,12 +339,12 @@ fn add_text<'a>(
|
|||
) -> EntityCommands<'a> {
|
||||
parent.spawn((
|
||||
Text::new(label),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 15.0,
|
||||
color,
|
||||
..default()
|
||||
},
|
||||
TextColor(color),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -598,8 +598,8 @@ fn update_ui_state(
|
|||
Color::WHITE
|
||||
};
|
||||
|
||||
writer.for_each_style(entity, |mut style| {
|
||||
style.color = color;
|
||||
writer.for_each_color(entity, |mut text_color| {
|
||||
text_color.0 = color;
|
||||
});
|
||||
|
||||
// Update the displayed value, if this is the currently-selected option.
|
||||
|
|
|
@ -35,7 +35,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// a place to display the extras on screen
|
||||
commands.spawn((
|
||||
Text::default(),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 15.,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -60,7 +60,7 @@ fn setup(
|
|||
// labels
|
||||
commands.spawn((
|
||||
Text::new("Perceptual Roughness"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 30.0,
|
||||
..default()
|
||||
},
|
||||
|
@ -74,7 +74,7 @@ fn setup(
|
|||
|
||||
commands.spawn((
|
||||
Text::new("Metallic"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 30.0,
|
||||
..default()
|
||||
},
|
||||
|
@ -92,7 +92,7 @@ fn setup(
|
|||
|
||||
commands.spawn((
|
||||
Text::new("Loading Environment Map..."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 30.0,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -172,11 +172,11 @@ fn setup_image_viewer_scene(
|
|||
|
||||
commands.spawn((
|
||||
Text::new("Drag and drop an HDR or EXR file"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 36.0,
|
||||
color: Color::BLACK,
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::BLACK),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
Style {
|
||||
align_self: AlignSelf::Center,
|
||||
|
|
|
@ -40,7 +40,7 @@ fn main() {
|
|||
}
|
||||
|
||||
impl AnimatableProperty for FontSizeProperty {
|
||||
type Component = TextStyle;
|
||||
type Component = TextFont;
|
||||
|
||||
type Property = f32;
|
||||
|
||||
|
@ -50,12 +50,12 @@ impl AnimatableProperty for FontSizeProperty {
|
|||
}
|
||||
|
||||
impl AnimatableProperty for TextColorProperty {
|
||||
type Component = TextStyle;
|
||||
type Component = TextColor;
|
||||
|
||||
type Property = Srgba;
|
||||
|
||||
fn get_mut(component: &mut Self::Component) -> Option<&mut Self::Property> {
|
||||
match component.color {
|
||||
match component.0 {
|
||||
Color::Srgba(ref mut color) => Some(color),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -172,12 +172,12 @@ fn setup(
|
|||
builder
|
||||
.spawn((
|
||||
Text::new("Bevy"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 24.0,
|
||||
color: Color::Srgba(Srgba::RED),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::Srgba(Srgba::RED)),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
))
|
||||
// Mark as an animation target.
|
||||
|
|
|
@ -37,12 +37,12 @@ impl AnimationEvent for MessageEvent {
|
|||
|
||||
fn edit_message(
|
||||
mut event_reader: EventReader<MessageEvent>,
|
||||
text: Single<(&mut Text2d, &mut TextStyle), With<MessageText>>,
|
||||
text: Single<(&mut Text2d, &mut TextColor), With<MessageText>>,
|
||||
) {
|
||||
let (mut text, mut style) = text.into_inner();
|
||||
let (mut text, mut color) = text.into_inner();
|
||||
for event in event_reader.read() {
|
||||
text.0 = event.value.clone();
|
||||
style.color = event.color;
|
||||
color.0 = event.color;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,11 +69,11 @@ fn setup(
|
|||
commands.spawn((
|
||||
MessageText,
|
||||
Text2d::default(),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 119.0,
|
||||
color: Color::NONE,
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::NONE),
|
||||
));
|
||||
|
||||
// Create a new animation clip.
|
||||
|
@ -108,9 +108,9 @@ fn setup(
|
|||
}
|
||||
|
||||
// Slowly fade out the text opacity.
|
||||
fn animate_text_opacity(mut styles: Query<&mut TextStyle>, time: Res<Time>) {
|
||||
for mut style in &mut styles {
|
||||
let a = style.color.alpha();
|
||||
style.color.set_alpha(a - time.delta_seconds());
|
||||
fn animate_text_opacity(mut colors: Query<&mut TextColor>, time: Res<Time>) {
|
||||
for mut color in &mut colors {
|
||||
let a = color.0.alpha();
|
||||
color.0.set_alpha(a - time.delta_seconds());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,11 +272,11 @@ fn setup_node_rects(commands: &mut Commands) {
|
|||
let text = commands
|
||||
.spawn((
|
||||
Text::new(node_string),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 16.0,
|
||||
color: ANTIQUE_WHITE.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(ANTIQUE_WHITE.into()),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
))
|
||||
.id();
|
||||
|
|
|
@ -237,19 +237,18 @@ fn setup_ui(mut commands: Commands) {
|
|||
// The button will automatically become a child of the parent that owns the
|
||||
// given `ChildBuilder`.
|
||||
fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, mask_group_id: u32) {
|
||||
let button_text_style = TextStyle {
|
||||
font_size: 14.0,
|
||||
color: Color::WHITE,
|
||||
..default()
|
||||
};
|
||||
let selected_button_text_style = TextStyle {
|
||||
color: Color::BLACK,
|
||||
..button_text_style.clone()
|
||||
};
|
||||
let label_text_style = TextStyle {
|
||||
color: Color::Srgba(LIGHT_GRAY),
|
||||
..button_text_style.clone()
|
||||
};
|
||||
let button_text_style = (
|
||||
TextFont {
|
||||
font_size: 14.0,
|
||||
..default()
|
||||
},
|
||||
TextColor::WHITE,
|
||||
);
|
||||
let selected_button_text_style = (button_text_style.0.clone(), TextColor::BLACK);
|
||||
let label_text_style = (
|
||||
button_text_style.0.clone(),
|
||||
TextColor(Color::Srgba(LIGHT_GRAY)),
|
||||
);
|
||||
|
||||
parent
|
||||
.spawn(NodeBundle {
|
||||
|
@ -493,8 +492,8 @@ fn update_ui(
|
|||
continue;
|
||||
};
|
||||
|
||||
writer.for_each_style(text, |mut style| {
|
||||
style.color = if enabled { Color::BLACK } else { Color::WHITE };
|
||||
writer.for_each_color(text, |mut color| {
|
||||
color.0 = if enabled { Color::BLACK } else { Color::WHITE };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ fn main() {
|
|||
fn setup(mut commands: Commands) {
|
||||
commands.spawn(Camera2d);
|
||||
|
||||
let text_style = TextStyle {
|
||||
let text_font = TextFont {
|
||||
font_size: 10.0,
|
||||
..default()
|
||||
};
|
||||
|
@ -64,10 +64,8 @@ fn setup(mut commands: Commands) {
|
|||
commands
|
||||
.spawn((
|
||||
Text2d(format!("{:?}", function)),
|
||||
TextStyle {
|
||||
color,
|
||||
..text_style.clone()
|
||||
},
|
||||
text_font.clone(),
|
||||
TextColor(color),
|
||||
Transform::from_xyz(
|
||||
i as f32 * 113.0 - 1280.0 / 2.0 + 25.0,
|
||||
-100.0 - ((j as f32 * 250.0) - 300.0),
|
||||
|
|
|
@ -182,11 +182,11 @@ fn setup_ui(mut commands: Commands) {
|
|||
.with_children(|b| {
|
||||
b.spawn((
|
||||
Text::new("Loading...".to_owned()),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 53.0,
|
||||
color: Color::BLACK,
|
||||
..Default::default()
|
||||
},
|
||||
TextColor(Color::BLACK),
|
||||
TextLayout::new_with_justify(JustifyText::Right),
|
||||
LoadingText,
|
||||
));
|
||||
|
|
|
@ -54,12 +54,9 @@ fn read_stream(receiver: Res<StreamReceiver>, mut events: EventWriter<StreamEven
|
|||
}
|
||||
|
||||
fn spawn_text(mut commands: Commands, mut reader: EventReader<StreamEvent>) {
|
||||
let text_style = TextStyle::default();
|
||||
|
||||
for (per_frame, event) in reader.read().enumerate() {
|
||||
commands.spawn((
|
||||
Text2d::new(event.0.to_string()),
|
||||
text_style.clone(),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
Transform::from_xyz(per_frame as f32 * 100.0, 300.0, 0.0),
|
||||
));
|
||||
|
|
|
@ -19,16 +19,16 @@ fn main() {
|
|||
DefaultPlugins,
|
||||
FpsOverlayPlugin {
|
||||
config: FpsOverlayConfig {
|
||||
text_config: TextStyle {
|
||||
text_config: TextFont {
|
||||
// Here we define size of our overlay
|
||||
font_size: 42.0,
|
||||
// We can also change color of the overlay
|
||||
color: OverlayColor::GREEN,
|
||||
// If we want, we can use a custom font
|
||||
font: default(),
|
||||
// We could also disable font smoothing,
|
||||
font_smoothing: FontSmoothing::default(),
|
||||
},
|
||||
// We can also change color of the overlay
|
||||
text_color: OverlayColor::GREEN,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
|
@ -67,10 +67,10 @@ fn setup(mut commands: Commands) {
|
|||
fn customize_config(input: Res<ButtonInput<KeyCode>>, mut overlay: ResMut<FpsOverlayConfig>) {
|
||||
if input.just_pressed(KeyCode::Digit1) {
|
||||
// Changing resource will affect overlay
|
||||
if overlay.text_config.color == OverlayColor::GREEN {
|
||||
overlay.text_config.color = OverlayColor::RED;
|
||||
if overlay.text_color == OverlayColor::GREEN {
|
||||
overlay.text_color = OverlayColor::RED;
|
||||
} else {
|
||||
overlay.text_config.color = OverlayColor::GREEN;
|
||||
overlay.text_color = OverlayColor::GREEN;
|
||||
}
|
||||
}
|
||||
if input.just_pressed(KeyCode::Digit2) {
|
||||
|
|
|
@ -76,10 +76,6 @@ fn setup(mut commands: Commands) {
|
|||
"Click on a \"Mine\" to trigger it.\n\
|
||||
When it explodes it will trigger all overlapping mines.",
|
||||
),
|
||||
TextStyle {
|
||||
color: Color::WHITE,
|
||||
..default()
|
||||
},
|
||||
Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(12.),
|
||||
|
|
|
@ -106,10 +106,7 @@ fn setup_ui(mut commands: Commands) {
|
|||
p.spawn(TextSpan::new("Last Triggered: "));
|
||||
p.spawn((
|
||||
TextSpan::new("-"),
|
||||
TextStyle {
|
||||
color: bevy::color::palettes::css::ORANGE.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(bevy::color::palettes::css::ORANGE.into()),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -177,11 +177,11 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut game: ResMu
|
|||
// scoreboard
|
||||
commands.spawn((
|
||||
Text::new("Score:"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.5, 0.5, 1.0),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.5, 0.5, 1.0)),
|
||||
Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(5.0),
|
||||
|
@ -405,10 +405,10 @@ fn display_score(mut commands: Commands, game: Res<Game>) {
|
|||
})
|
||||
.with_child((
|
||||
Text::new(format!("Cake eaten: {}", game.cake_eaten)),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 67.0,
|
||||
color: Color::srgb(0.5, 0.5, 1.0),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.5, 0.5, 1.0)),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -219,11 +219,11 @@ fn setup(
|
|||
commands
|
||||
.spawn((
|
||||
Text::new("Score: "),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: SCOREBOARD_FONT_SIZE,
|
||||
color: TEXT_COLOR,
|
||||
..default()
|
||||
},
|
||||
TextColor(TEXT_COLOR),
|
||||
ScoreboardUi,
|
||||
Style {
|
||||
position_type: PositionType::Absolute,
|
||||
|
@ -234,11 +234,11 @@ fn setup(
|
|||
))
|
||||
.with_child((
|
||||
TextSpan::default(),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: SCOREBOARD_FONT_SIZE,
|
||||
color: SCORE_COLOR,
|
||||
..default()
|
||||
},
|
||||
TextColor(SCORE_COLOR),
|
||||
));
|
||||
|
||||
// Walls
|
||||
|
|
|
@ -128,7 +128,7 @@ fn setup_contributor_selection(mut commands: Commands, asset_server: Res<AssetSe
|
|||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
commands.spawn(Camera2d);
|
||||
|
||||
let text_style = TextStyle {
|
||||
let text_style = TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 60.0,
|
||||
..default()
|
||||
|
@ -148,7 +148,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
))
|
||||
.with_child((
|
||||
TextSpan::default(),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 30.,
|
||||
..text_style
|
||||
},
|
||||
|
@ -216,7 +216,7 @@ fn select(
|
|||
contributor.num_commits,
|
||||
if contributor.num_commits > 1 { "s" } else { "" }
|
||||
);
|
||||
writer.style(entity, 0).color = sprite.color;
|
||||
writer.color(entity, 0).0 = sprite.color;
|
||||
}
|
||||
|
||||
/// Change the tint color to the "deselected" color and push
|
||||
|
|
|
@ -107,7 +107,7 @@ fn setup(
|
|||
|
||||
// Spawn the text instructions
|
||||
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
|
||||
let text_style = TextStyle {
|
||||
let text_style = TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 25.0,
|
||||
..default()
|
||||
|
|
|
@ -176,11 +176,11 @@ mod game {
|
|||
.with_children(|p| {
|
||||
p.spawn((
|
||||
Text::new("Will be back to the menu shortly..."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 67.0,
|
||||
color: TEXT_COLOR,
|
||||
..default()
|
||||
},
|
||||
TextColor(TEXT_COLOR),
|
||||
Style {
|
||||
margin: UiRect::all(Val::Px(50.0)),
|
||||
..default()
|
||||
|
@ -196,27 +196,27 @@ mod game {
|
|||
.with_children(|p| {
|
||||
p.spawn((
|
||||
TextSpan(format!("quality: {:?}", *display_quality)),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 50.0,
|
||||
color: BLUE.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(BLUE.into()),
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan::new(" - "),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 50.0,
|
||||
color: TEXT_COLOR,
|
||||
..default()
|
||||
},
|
||||
TextColor(TEXT_COLOR),
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan(format!("volume: {:?}", *volume)),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 50.0,
|
||||
color: LIME.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(LIME.into()),
|
||||
));
|
||||
});
|
||||
});
|
||||
|
@ -398,9 +398,8 @@ mod menu {
|
|||
left: Val::Px(10.0),
|
||||
..default()
|
||||
};
|
||||
let button_text_style = TextStyle {
|
||||
let button_text_font = TextFont {
|
||||
font_size: 33.0,
|
||||
color: TEXT_COLOR,
|
||||
..default()
|
||||
};
|
||||
|
||||
|
@ -433,11 +432,11 @@ mod menu {
|
|||
// Display the game name
|
||||
parent.spawn((
|
||||
Text::new("Bevy Game Menu UI"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 67.0,
|
||||
color: TEXT_COLOR,
|
||||
..default()
|
||||
},
|
||||
TextColor(TEXT_COLOR),
|
||||
Style {
|
||||
margin: UiRect::all(Val::Px(50.0)),
|
||||
..default()
|
||||
|
@ -464,7 +463,11 @@ mod menu {
|
|||
image: UiImage::new(icon),
|
||||
..default()
|
||||
});
|
||||
parent.spawn((Text::new("New Game"), button_text_style.clone()));
|
||||
parent.spawn((
|
||||
Text::new("New Game"),
|
||||
button_text_font.clone(),
|
||||
TextColor(TEXT_COLOR),
|
||||
));
|
||||
});
|
||||
parent
|
||||
.spawn((
|
||||
|
@ -482,7 +485,11 @@ mod menu {
|
|||
image: UiImage::new(icon),
|
||||
..default()
|
||||
});
|
||||
parent.spawn((Text::new("Settings"), button_text_style.clone()));
|
||||
parent.spawn((
|
||||
Text::new("Settings"),
|
||||
button_text_font.clone(),
|
||||
TextColor(TEXT_COLOR),
|
||||
));
|
||||
});
|
||||
parent
|
||||
.spawn((
|
||||
|
@ -500,7 +507,11 @@ mod menu {
|
|||
image: UiImage::new(icon),
|
||||
..default()
|
||||
});
|
||||
parent.spawn((Text::new("Quit"), button_text_style));
|
||||
parent.spawn((
|
||||
Text::new("Quit"),
|
||||
button_text_font,
|
||||
TextColor(TEXT_COLOR),
|
||||
));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -516,11 +527,13 @@ mod menu {
|
|||
..default()
|
||||
};
|
||||
|
||||
let button_text_style = TextStyle {
|
||||
font_size: 33.0,
|
||||
color: TEXT_COLOR,
|
||||
..default()
|
||||
};
|
||||
let button_text_style = (
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
..default()
|
||||
},
|
||||
TextColor(TEXT_COLOR),
|
||||
);
|
||||
|
||||
commands
|
||||
.spawn((
|
||||
|
@ -579,11 +592,13 @@ mod menu {
|
|||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
};
|
||||
let button_text_style = TextStyle {
|
||||
font_size: 33.0,
|
||||
color: TEXT_COLOR,
|
||||
..default()
|
||||
};
|
||||
let button_text_style = (
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
..default()
|
||||
},
|
||||
TextColor(TEXT_COLOR),
|
||||
);
|
||||
|
||||
commands
|
||||
.spawn((
|
||||
|
@ -683,11 +698,13 @@ mod menu {
|
|||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
};
|
||||
let button_text_style = TextStyle {
|
||||
font_size: 33.0,
|
||||
color: TEXT_COLOR,
|
||||
..default()
|
||||
};
|
||||
let button_text_style = (
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
..default()
|
||||
},
|
||||
TextColor(TEXT_COLOR),
|
||||
);
|
||||
|
||||
commands
|
||||
.spawn((
|
||||
|
|
|
@ -77,7 +77,7 @@ fn setup(mut commands: Commands) {
|
|||
commands.insert_resource(level_data);
|
||||
|
||||
// Spawns the UI that will show the user prompts.
|
||||
let text_style = TextStyle {
|
||||
let text_style = TextFont {
|
||||
font_size: 42.0,
|
||||
..default()
|
||||
};
|
||||
|
@ -239,7 +239,7 @@ struct LoadingScreen;
|
|||
|
||||
// Spawns the necessary components for the loading screen.
|
||||
fn load_loading_screen(mut commands: Commands) {
|
||||
let text_style = TextStyle {
|
||||
let text_style = TextFont {
|
||||
font_size: 67.0,
|
||||
..default()
|
||||
};
|
||||
|
|
|
@ -116,11 +116,11 @@ fn build_ui(
|
|||
let schedule = schedules.get(*label).unwrap();
|
||||
text_spans.push((
|
||||
TextSpan(format!("{label:?}\n")),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load(FONT_BOLD),
|
||||
color: FONT_COLOR,
|
||||
..default()
|
||||
},
|
||||
TextColor(FONT_COLOR),
|
||||
));
|
||||
|
||||
// grab the list of systems in the schedule, in the order the
|
||||
|
@ -144,19 +144,15 @@ fn build_ui(
|
|||
// Add a text section for displaying the cursor for this system
|
||||
text_spans.push((
|
||||
TextSpan::new(" "),
|
||||
TextStyle {
|
||||
color: FONT_COLOR,
|
||||
..default()
|
||||
},
|
||||
TextFont::default(),
|
||||
TextColor(FONT_COLOR),
|
||||
));
|
||||
|
||||
// add the name of the system to the ui
|
||||
text_spans.push((
|
||||
TextSpan(format!("{}\n", system.name())),
|
||||
TextStyle {
|
||||
color: FONT_COLOR,
|
||||
..default()
|
||||
},
|
||||
TextFont::default(),
|
||||
TextColor(FONT_COLOR),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -196,11 +192,11 @@ fn build_stepping_hint(mut commands: Commands) {
|
|||
// stepping description box
|
||||
commands.spawn((
|
||||
Text::new(hint_text),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 15.0,
|
||||
color: FONT_COLOR,
|
||||
..default()
|
||||
},
|
||||
TextColor(FONT_COLOR),
|
||||
Style {
|
||||
position_type: PositionType::Absolute,
|
||||
bottom: Val::Px(5.0),
|
||||
|
|
|
@ -134,11 +134,11 @@ pub fn spawn_ui_text<'a>(
|
|||
) -> EntityCommands<'a> {
|
||||
parent.spawn((
|
||||
Text::new(label),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 18.0,
|
||||
color,
|
||||
..default()
|
||||
},
|
||||
TextColor(color),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -166,12 +166,12 @@ pub fn update_ui_radio_button(background_color: &mut BackgroundColor, selected:
|
|||
background_color.0 = if selected { Color::WHITE } else { Color::BLACK };
|
||||
}
|
||||
|
||||
/// Updates the style of the label of a radio button to reflect its selected
|
||||
/// Updates the color of the label of a radio button to reflect its selected
|
||||
/// status.
|
||||
pub fn update_ui_radio_button_text(entity: Entity, writer: &mut UiTextWriter, selected: bool) {
|
||||
let text_color = if selected { Color::BLACK } else { Color::WHITE };
|
||||
|
||||
writer.for_each_style(entity, |mut style| {
|
||||
style.color = text_color;
|
||||
writer.for_each_color(entity, |mut color| {
|
||||
color.0 = text_color;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
p.spawn(TextSpan::new("IME Buffer: "));
|
||||
p.spawn((
|
||||
TextSpan::new("\n"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
..default()
|
||||
},
|
||||
|
@ -64,7 +64,7 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
|
||||
commands.spawn((
|
||||
Text2d::new(""),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font,
|
||||
font_size: 100.0,
|
||||
..default()
|
||||
|
@ -137,7 +137,7 @@ fn listen_ime_events(
|
|||
fn listen_keyboard_input_events(
|
||||
mut commands: Commands,
|
||||
mut events: EventReader<KeyboardInput>,
|
||||
mut edit_text: Query<(&mut Text2d, &TextStyle), (Without<Node>, Without<Bubble>)>,
|
||||
mut edit_text: Query<(&mut Text2d, &TextFont), (Without<Node>, Without<Bubble>)>,
|
||||
) {
|
||||
for event in events.read() {
|
||||
// Only trigger changes when the key is first pressed.
|
||||
|
|
|
@ -75,7 +75,7 @@ fn setup(mut commands: Commands) {
|
|||
C: Toggle cyclic curve construction";
|
||||
let spline_mode_text = format!("Spline: {spline_mode}");
|
||||
let cycling_mode_text = format!("{cycling_mode}");
|
||||
let style = TextStyle::default();
|
||||
let style = TextFont::default();
|
||||
|
||||
commands
|
||||
.spawn(NodeBundle {
|
||||
|
|
|
@ -132,11 +132,11 @@ fn setup_scene(
|
|||
})
|
||||
.with_child((
|
||||
Text::new("Test Button"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 30.0,
|
||||
color: Color::BLACK,
|
||||
..default()
|
||||
},
|
||||
TextColor::BLACK,
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ fn spawn_text(mut commands: Commands) {
|
|||
})
|
||||
.with_child((
|
||||
Text::new("Move the player with WASD"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 25.0,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -42,15 +42,15 @@ fn setup(
|
|||
},
|
||||
)
|
||||
.observe(
|
||||
|evt: Trigger<Pointer<Out>>, mut texts: Query<&mut TextStyle>| {
|
||||
let mut style = texts.get_mut(evt.entity()).unwrap();
|
||||
style.color = Color::WHITE;
|
||||
|evt: Trigger<Pointer<Out>>, mut texts: Query<&mut TextColor>| {
|
||||
let mut color = texts.get_mut(evt.entity()).unwrap();
|
||||
color.0 = Color::WHITE;
|
||||
},
|
||||
)
|
||||
.observe(
|
||||
|evt: Trigger<Pointer<Over>>, mut texts: Query<&mut TextStyle>| {
|
||||
let mut style = texts.get_mut(evt.entity()).unwrap();
|
||||
style.color = CYAN_400.into();
|
||||
|evt: Trigger<Pointer<Over>>, mut texts: Query<&mut TextColor>| {
|
||||
let mut color = texts.get_mut(evt.entity()).unwrap();
|
||||
color.0 = CYAN_400.into();
|
||||
},
|
||||
);
|
||||
// circular base
|
||||
|
|
|
@ -148,7 +148,7 @@ fn infotext_system(mut commands: Commands) {
|
|||
commands.spawn(Camera2d);
|
||||
commands.spawn((
|
||||
Text::new("Nothing to see in this window! Check the console output!"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 42.0,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -229,8 +229,8 @@ fn toggle_prepass_view(
|
|||
};
|
||||
let text = text.single();
|
||||
*writer.text(text, 1) = format!("Prepass Output: {label}\n");
|
||||
writer.for_each_style(text, |mut style| {
|
||||
style.color = Color::WHITE;
|
||||
writer.for_each_color(text, |mut color| {
|
||||
color.0 = Color::WHITE;
|
||||
});
|
||||
|
||||
let handle = material_handle.single();
|
||||
|
|
|
@ -370,11 +370,11 @@ mod ui {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Play"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
|
||||
|
@ -402,11 +402,11 @@ mod ui {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Tutorial"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
})
|
||||
|
@ -500,11 +500,11 @@ mod ui {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Paused"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
});
|
||||
|
@ -532,11 +532,11 @@ mod ui {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("TURBO MODE"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.3, 0.1),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.3, 0.1)),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
@ -574,37 +574,37 @@ mod ui {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Move the bevy logo with the arrow keys"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.3, 0.3, 0.7),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.3, 0.3, 0.7)),
|
||||
));
|
||||
parent.spawn((
|
||||
Text::new("Press T to enter TURBO MODE"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.3, 0.3, 0.7),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.3, 0.3, 0.7)),
|
||||
));
|
||||
|
||||
parent.spawn((
|
||||
Text::new("Press SPACE to pause"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.3, 0.3, 0.7),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.3, 0.3, 0.7)),
|
||||
));
|
||||
|
||||
parent.spawn((
|
||||
Text::new("Press ESCAPE to return to the menu"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.3, 0.3, 0.7),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.3, 0.3, 0.7)),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
@ -631,20 +631,20 @@ mod ui {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Press SPACE to resume"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.3, 0.3, 0.7),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.3, 0.3, 0.7)),
|
||||
));
|
||||
|
||||
parent.spawn((
|
||||
Text::new("Press ESCAPE to return to the menu"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.3, 0.3, 0.7),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.3, 0.3, 0.7)),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -272,11 +272,11 @@ fn setup_menu(mut commands: Commands) {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Play"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
})
|
||||
|
|
|
@ -80,11 +80,11 @@ fn setup_menu(mut commands: Commands) {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Play"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
})
|
||||
|
|
|
@ -185,11 +185,11 @@ mod ui {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Play"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
})
|
||||
|
@ -237,11 +237,11 @@ mod ui {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Paused"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -255,16 +255,9 @@ fn setup(
|
|||
transform_rng: ChaCha8Rng::seed_from_u64(42),
|
||||
};
|
||||
|
||||
let lime_text = TextStyle {
|
||||
let font = TextFont {
|
||||
font_size: 40.0,
|
||||
color: LIME.into(),
|
||||
..default()
|
||||
};
|
||||
|
||||
let aqua_text = TextStyle {
|
||||
font_size: 40.0,
|
||||
color: LIME.into(),
|
||||
..default()
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
commands.spawn(Camera2d);
|
||||
|
@ -283,14 +276,30 @@ fn setup(
|
|||
))
|
||||
.with_children(|p| {
|
||||
p.spawn((Text::default(), StatsText)).with_children(|p| {
|
||||
p.spawn((TextSpan::new("Bird Count: "), lime_text.clone()));
|
||||
p.spawn((TextSpan::new(""), aqua_text.clone()));
|
||||
p.spawn((TextSpan::new("\nFPS (raw): "), lime_text.clone()));
|
||||
p.spawn((TextSpan::new(""), aqua_text.clone()));
|
||||
p.spawn((TextSpan::new("\nFPS (SMA): "), lime_text.clone()));
|
||||
p.spawn((TextSpan::new(""), aqua_text.clone()));
|
||||
p.spawn((TextSpan::new("\nFPS (EMA): "), lime_text.clone()));
|
||||
p.spawn((TextSpan::new(""), aqua_text.clone()));
|
||||
p.spawn((
|
||||
TextSpan::new("Bird Count: "),
|
||||
font.clone(),
|
||||
TextColor(LIME.into()),
|
||||
));
|
||||
p.spawn((TextSpan::new(""), font.clone(), TextColor(AQUA.into())));
|
||||
p.spawn((
|
||||
TextSpan::new("\nFPS (raw): "),
|
||||
font.clone(),
|
||||
TextColor(LIME.into()),
|
||||
));
|
||||
p.spawn((TextSpan::new(""), font.clone(), TextColor(AQUA.into())));
|
||||
p.spawn((
|
||||
TextSpan::new("\nFPS (SMA): "),
|
||||
font.clone(),
|
||||
TextColor(LIME.into()),
|
||||
));
|
||||
p.spawn((TextSpan::new(""), font.clone(), TextColor(AQUA.into())));
|
||||
p.spawn((
|
||||
TextSpan::new("\nFPS (EMA): "),
|
||||
font.clone(),
|
||||
TextColor(LIME.into()),
|
||||
));
|
||||
p.spawn((TextSpan::new(""), font.clone(), TextColor(AQUA.into())));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ use bevy::{
|
|||
color::palettes::css::ORANGE_RED,
|
||||
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
||||
prelude::*,
|
||||
text::TextColor,
|
||||
window::{PresentMode, WindowResolution},
|
||||
winit::{UpdateMode, WinitSettings},
|
||||
};
|
||||
|
@ -69,7 +70,7 @@ fn main() {
|
|||
focused_mode: UpdateMode::Continuous,
|
||||
unfocused_mode: UpdateMode::Continuous,
|
||||
})
|
||||
.add_systems(Update, button_system);
|
||||
.add_systems(Update, (button_system, set_text_colors_changed));
|
||||
|
||||
if args.grid {
|
||||
app.add_systems(Startup, setup_grid);
|
||||
|
@ -96,6 +97,12 @@ fn main() {
|
|||
app.insert_resource(args).run();
|
||||
}
|
||||
|
||||
fn set_text_colors_changed(mut colors: Query<&mut TextColor>) {
|
||||
for mut text_color in colors.iter_mut() {
|
||||
text_color.set_changed();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct IdleColor(Color);
|
||||
|
||||
|
@ -264,11 +271,11 @@ fn spawn_button(
|
|||
builder.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text(format!("{column}, {row}")),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: FONT_SIZE,
|
||||
color: Color::srgb(0.2, 0.2, 0.2),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.2, 0.2, 0.2)),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ fn setup(mut commands: Commands) {
|
|||
|
||||
commands.spawn(Camera2d);
|
||||
let text_string = "0123456789".repeat(10_000);
|
||||
let text_style = TextStyle {
|
||||
let text_font = TextFont {
|
||||
font_size: 4.,
|
||||
..Default::default()
|
||||
};
|
||||
|
@ -74,15 +74,12 @@ fn setup(mut commands: Commands) {
|
|||
},
|
||||
..Default::default()
|
||||
})
|
||||
.with_child((Text(text_string.clone()), text_style.clone(), text_block));
|
||||
.with_child((Text(text_string.clone()), text_font.clone(), text_block));
|
||||
});
|
||||
|
||||
commands.spawn((
|
||||
Text2d::new(text_string),
|
||||
TextStyle {
|
||||
color: RED.into(),
|
||||
..text_style
|
||||
},
|
||||
TextColor(RED.into()),
|
||||
bevy::sprite::Anchor::Center,
|
||||
TextBounds::new_horizontal(1000.),
|
||||
text_block,
|
||||
|
|
|
@ -44,21 +44,21 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
[
|
||||
(
|
||||
TextSpan("text".repeat(i)),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: (4 + i % 10) as f32,
|
||||
color: BLUE.into(),
|
||||
..Default::default()
|
||||
},
|
||||
TextColor(BLUE.into()),
|
||||
),
|
||||
(
|
||||
TextSpan("pipeline".repeat(i)),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: (4 + i % 11) as f32,
|
||||
color: YELLOW.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(YELLOW.into()),
|
||||
),
|
||||
]
|
||||
};
|
||||
|
|
|
@ -93,7 +93,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut time: ResMu
|
|||
// real time info
|
||||
builder.spawn((
|
||||
Text::default(),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size,
|
||||
..default()
|
||||
},
|
||||
|
@ -103,22 +103,22 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut time: ResMu
|
|||
// keybindings
|
||||
builder.spawn((
|
||||
Text::new("CONTROLS\nUn/Pause: Space\nSpeed+: Up\nSpeed-: Down"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size,
|
||||
color: Color::srgb(0.85, 0.85, 0.85),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.85, 0.85, 0.85)),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
));
|
||||
|
||||
// virtual time info
|
||||
builder.spawn((
|
||||
Text::default(),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size,
|
||||
color: virtual_color,
|
||||
..default()
|
||||
},
|
||||
TextColor(virtual_color),
|
||||
TextLayout::new_with_justify(JustifyText::Right),
|
||||
VirtualTime,
|
||||
));
|
||||
|
|
|
@ -297,7 +297,7 @@ fn setup_sticks(
|
|||
Transform::from_xyz(dead_mid, dead_mid, 3.),
|
||||
));
|
||||
// text
|
||||
let style = TextStyle {
|
||||
let style = TextFont {
|
||||
font_size: 13.,
|
||||
..default()
|
||||
};
|
||||
|
@ -362,7 +362,7 @@ fn setup_triggers(
|
|||
parent.spawn((
|
||||
Transform::from_xyz(0., 0., 1.),
|
||||
Text(format!("{:.3}", 0.)),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 13.,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -122,7 +122,7 @@ impl fmt::Display for Target {
|
|||
}
|
||||
}
|
||||
impl Target {
|
||||
fn text_span(&self, key: &str, style: TextStyle) -> (String, TextStyle) {
|
||||
fn text_span(&self, key: &str, style: TextFont) -> (String, TextFont) {
|
||||
(format!("[{key}] {self}\n"), style)
|
||||
}
|
||||
fn new(
|
||||
|
@ -253,7 +253,7 @@ fn detect_morphs(
|
|||
detected.extend(targets);
|
||||
}
|
||||
detected.truncate(AVAILABLE_KEYS.len());
|
||||
let style = TextStyle {
|
||||
let style = TextFont {
|
||||
font_size: 13.0,
|
||||
..default()
|
||||
};
|
||||
|
|
|
@ -161,7 +161,7 @@ fn setup(mut commands: Commands) {
|
|||
let label_node = commands
|
||||
.spawn((
|
||||
Text::new(label),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 9.0,
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -230,7 +230,7 @@ fn setup(mut commands: Commands) {
|
|||
let label_node = commands
|
||||
.spawn((
|
||||
Text::new(label),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 9.0,
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -267,7 +267,7 @@ fn setup(mut commands: Commands) {
|
|||
.with_children(|builder| {
|
||||
builder.spawn((
|
||||
Text::new("Borders"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 20.0,
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -292,7 +292,7 @@ fn setup(mut commands: Commands) {
|
|||
.with_children(|builder| {
|
||||
builder.spawn((
|
||||
Text::new("Borders Rounded"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 20.0,
|
||||
..Default::default()
|
||||
},
|
||||
|
|
|
@ -85,12 +85,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
})
|
||||
.with_child((
|
||||
Text::new("Button"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ impl TargetUpdate for Target<Visibility> {
|
|||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
let palette: [Color; 4] = PALETTE.map(|hex| Srgba::hex(hex).unwrap().into());
|
||||
|
||||
let text_style = TextStyle {
|
||||
let text_font = TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
..default()
|
||||
};
|
||||
|
@ -95,7 +95,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
..Default::default()
|
||||
}).with_children(|parent| {
|
||||
parent.spawn((Text::new("Use the panel on the right to change the Display and Visibility properties for the respective nodes of the panel on the left"),
|
||||
text_style.clone(),
|
||||
text_font.clone(),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
Style {
|
||||
margin: UiRect::bottom(Val::Px(10.)),
|
||||
|
@ -133,7 +133,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
},
|
||||
..Default::default()
|
||||
}).with_children(|parent| {
|
||||
spawn_right_panel(parent, text_style, &palette, target_ids);
|
||||
spawn_right_panel(parent, text_font, &palette, target_ids);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -147,21 +147,23 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
},
|
||||
..default() })
|
||||
.with_children(|builder| {
|
||||
let text_style = TextStyle {
|
||||
let text_font = TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
..default()
|
||||
};
|
||||
|
||||
builder.spawn((Text::new("Display::None\nVisibility::Hidden\nVisibility::Inherited"),
|
||||
TextStyle { color: HIDDEN_COLOR, ..text_style.clone() },
|
||||
text_font.clone(),
|
||||
TextColor(HIDDEN_COLOR),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
));
|
||||
builder.spawn((Text::new("-\n-\n-"),
|
||||
TextStyle { color: DARK_GRAY.into(), ..text_style.clone() },
|
||||
text_font.clone(),
|
||||
TextColor(DARK_GRAY.into()),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
));
|
||||
builder.spawn((Text::new("The UI Node and its descendants will not be visible and will not be allotted any space in the UI layout.\nThe UI Node will not be visible but will still occupy space in the UI layout.\nThe UI node will inherit the visibility property of its parent. If it has no parent it will be visible."),
|
||||
text_style
|
||||
text_font
|
||||
));
|
||||
});
|
||||
});
|
||||
|
@ -275,13 +277,13 @@ fn spawn_left_panel(builder: &mut ChildBuilder, palette: &[Color; 4]) -> Vec<Ent
|
|||
|
||||
fn spawn_right_panel(
|
||||
parent: &mut ChildBuilder,
|
||||
text_style: TextStyle,
|
||||
text_font: TextFont,
|
||||
palette: &[Color; 4],
|
||||
mut target_ids: Vec<Entity>,
|
||||
) {
|
||||
let spawn_buttons = |parent: &mut ChildBuilder, target_id| {
|
||||
spawn_button::<Display>(parent, text_style.clone(), target_id);
|
||||
spawn_button::<Visibility>(parent, text_style.clone(), target_id);
|
||||
spawn_button::<Display>(parent, text_font.clone(), target_id);
|
||||
spawn_button::<Visibility>(parent, text_font.clone(), target_id);
|
||||
};
|
||||
parent
|
||||
.spawn(NodeBundle {
|
||||
|
@ -392,7 +394,7 @@ fn spawn_right_panel(
|
|||
});
|
||||
}
|
||||
|
||||
fn spawn_button<T>(parent: &mut ChildBuilder, text_style: TextStyle, target: Entity)
|
||||
fn spawn_button<T>(parent: &mut ChildBuilder, text_font: TextFont, target: Entity)
|
||||
where
|
||||
T: Default + std::fmt::Debug + Send + Sync + 'static,
|
||||
Target<T>: TargetUpdate,
|
||||
|
@ -413,7 +415,7 @@ where
|
|||
.with_children(|builder| {
|
||||
builder.spawn((
|
||||
Text(format!("{}::{:?}", Target::<T>::NAME, T::default())),
|
||||
text_style,
|
||||
text_font,
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
));
|
||||
});
|
||||
|
@ -422,7 +424,7 @@ where
|
|||
fn buttons_handler<T>(
|
||||
mut left_panel_query: Query<&mut <Target<T> as TargetUpdate>::TargetComponent>,
|
||||
mut visibility_button_query: Query<(&Target<T>, &Interaction, &Children), Changed<Interaction>>,
|
||||
mut text_query: Query<(&mut Text, &mut TextStyle)>,
|
||||
mut text_query: Query<(&mut Text, &mut TextColor)>,
|
||||
) where
|
||||
T: Send + Sync,
|
||||
Target<T>: TargetUpdate + Component,
|
||||
|
@ -431,9 +433,9 @@ fn buttons_handler<T>(
|
|||
if matches!(interaction, Interaction::Pressed) {
|
||||
let mut target_value = left_panel_query.get_mut(target.id).unwrap();
|
||||
for &child in children {
|
||||
if let Ok((mut text, mut style)) = text_query.get_mut(child) {
|
||||
if let Ok((mut text, mut text_color)) = text_query.get_mut(child) {
|
||||
**text = target.update_target(target_value.as_mut());
|
||||
style.color = if text.contains("None") || text.contains("Hidden") {
|
||||
text_color.0 = if text.contains("None") || text.contains("Hidden") {
|
||||
Color::srgb(1.0, 0.7, 0.7)
|
||||
} else {
|
||||
Color::WHITE
|
||||
|
@ -446,24 +448,24 @@ fn buttons_handler<T>(
|
|||
|
||||
fn text_hover(
|
||||
mut button_query: Query<(&Interaction, &mut BackgroundColor, &Children), Changed<Interaction>>,
|
||||
mut text_query: Query<(&Text, &mut TextStyle)>,
|
||||
mut text_query: Query<(&Text, &mut TextColor)>,
|
||||
) {
|
||||
for (interaction, mut color, children) in button_query.iter_mut() {
|
||||
match interaction {
|
||||
Interaction::Hovered => {
|
||||
*color = Color::BLACK.with_alpha(0.6).into();
|
||||
for &child in children {
|
||||
if let Ok((_, mut style)) = text_query.get_mut(child) {
|
||||
if let Ok((_, mut text_color)) = text_query.get_mut(child) {
|
||||
// Bypass change detection to avoid recomputation of the text when only changing the color
|
||||
style.bypass_change_detection().color = YELLOW.into();
|
||||
text_color.bypass_change_detection().0 = YELLOW.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
*color = Color::BLACK.with_alpha(0.5).into();
|
||||
for &child in children {
|
||||
if let Ok((text, mut style)) = text_query.get_mut(child) {
|
||||
style.bypass_change_detection().color =
|
||||
if let Ok((text, mut text_color)) = text_query.get_mut(child) {
|
||||
text_color.bypass_change_detection().0 =
|
||||
if text.contains("None") || text.contains("Hidden") {
|
||||
HIDDEN_COLOR
|
||||
} else {
|
||||
|
|
|
@ -175,11 +175,8 @@ fn spawn_nested_text_bundle(
|
|||
.with_children(|builder| {
|
||||
builder.spawn((
|
||||
Text::new(text),
|
||||
TextStyle {
|
||||
font,
|
||||
color: Color::BLACK,
|
||||
..default()
|
||||
},
|
||||
TextFont { font, ..default() },
|
||||
TextColor::BLACK,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -98,12 +98,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut state: ResM
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("a"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font_handle,
|
||||
font_size: 50.0,
|
||||
color: YELLOW.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(YELLOW.into()),
|
||||
));
|
||||
});
|
||||
// We're seeding the PRNG here to make this example deterministic for testing purposes.
|
||||
|
|
|
@ -87,15 +87,15 @@ fn create_button() -> ButtonBundle {
|
|||
}
|
||||
}
|
||||
|
||||
fn create_label(text: &str, font: Handle<Font>) -> (Text, TextStyle) {
|
||||
fn create_label(text: &str, font: Handle<Font>) -> (Text, TextFont, TextColor) {
|
||||
(
|
||||
Text::new(text),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font,
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -137,13 +137,13 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
})
|
||||
.with_children(|builder| {
|
||||
builder.spawn((Text::new("Sidebar"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
..default()
|
||||
},
|
||||
));
|
||||
builder.spawn((Text::new("A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 13.0,
|
||||
..default()
|
||||
|
@ -210,10 +210,7 @@ fn item_rect(builder: &mut ChildBuilder, color: Srgba) {
|
|||
fn spawn_nested_text_bundle(builder: &mut ChildBuilder, font: Handle<Font>, text: &str) {
|
||||
builder.spawn((
|
||||
Text::new(text),
|
||||
TextStyle {
|
||||
font,
|
||||
color: Color::BLACK,
|
||||
..default()
|
||||
},
|
||||
TextFont { font, ..default() },
|
||||
TextColor::BLACK,
|
||||
));
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ fn main() {
|
|||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
commands.spawn(Camera2d);
|
||||
|
||||
let text_style = TextStyle::default();
|
||||
let text_style = TextFont::default();
|
||||
|
||||
let image = asset_server.load("branding/icon.png");
|
||||
|
||||
|
|
|
@ -81,14 +81,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
|
||||
// Instructions
|
||||
|
||||
let text_style = TextStyle::default();
|
||||
let text_font = TextFont::default();
|
||||
|
||||
commands
|
||||
.spawn((
|
||||
Text::new(
|
||||
"Next Overflow Setting (O)\nNext Container Size (S)\nToggle Animation (space)\n\n",
|
||||
),
|
||||
text_style.clone(),
|
||||
text_font.clone(),
|
||||
Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(12.0),
|
||||
|
@ -99,7 +99,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
))
|
||||
.with_child((
|
||||
TextSpan::new(format!("{:?}", Overflow::clip())),
|
||||
text_style.clone(),
|
||||
text_font.clone(),
|
||||
));
|
||||
|
||||
// Overflow Debug
|
||||
|
@ -168,7 +168,7 @@ fn spawn_text(
|
|||
spawn_container(parent, update_transform, |parent| {
|
||||
parent.spawn((
|
||||
Text::new("Bevy"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 100.0,
|
||||
..default()
|
||||
|
|
|
@ -56,12 +56,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
|
||||
parent.spawn((
|
||||
Text::new("(0.0, 0.0)"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
@ -69,11 +69,11 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
/// This systems polls the relative cursor position and displays its value in a text component.
|
||||
fn relative_cursor_position_system(
|
||||
relative_cursor_position_query: Query<&RelativeCursorPosition>,
|
||||
mut output_query: Query<(&mut Text, &mut TextStyle)>,
|
||||
mut output_query: Query<(&mut Text, &mut TextColor)>,
|
||||
) {
|
||||
let relative_cursor_position = relative_cursor_position_query.single();
|
||||
|
||||
let (mut output, mut style) = output_query.single_mut();
|
||||
let (mut output, mut text_color) = output_query.single_mut();
|
||||
|
||||
**output = if let Some(relative_cursor_position) = relative_cursor_position.normalized {
|
||||
format!(
|
||||
|
@ -84,7 +84,7 @@ fn relative_cursor_position_system(
|
|||
"unknown".to_string()
|
||||
};
|
||||
|
||||
style.color = if relative_cursor_position.mouse_over() {
|
||||
text_color.0 = if relative_cursor_position.mouse_over() {
|
||||
Color::srgb(0.1, 0.9, 0.1)
|
||||
} else {
|
||||
Color::srgb(0.9, 0.1, 0.1)
|
||||
|
|
|
@ -83,11 +83,11 @@ fn setup(
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("This is a cube"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 40.0,
|
||||
color: Color::BLACK,
|
||||
..default()
|
||||
},
|
||||
TextColor::BLACK,
|
||||
));
|
||||
});
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// header
|
||||
parent.spawn((
|
||||
Text::new("Horizontally Scrolling list (Ctrl + Mousewheel)"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: FONT_SIZE,
|
||||
..default()
|
||||
|
@ -80,7 +80,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.with_children(|parent| {
|
||||
for i in 0..100 {
|
||||
parent.spawn((Text(format!("Item {i}")),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server
|
||||
.load("fonts/FiraSans-Bold.ttf"),
|
||||
..default()
|
||||
|
@ -138,7 +138,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// Title
|
||||
parent.spawn((
|
||||
Text::new("Vertically Scrolling List"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: FONT_SIZE,
|
||||
..default()
|
||||
|
@ -178,7 +178,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
parent
|
||||
.spawn((
|
||||
Text(format!("Item {i}")),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server
|
||||
.load("fonts/FiraSans-Bold.ttf"),
|
||||
..default()
|
||||
|
@ -213,7 +213,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// Title
|
||||
parent.spawn((
|
||||
Text::new("Bidirectionally Scrolling List"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: FONT_SIZE,
|
||||
..default()
|
||||
|
@ -251,7 +251,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
parent
|
||||
.spawn((
|
||||
Text(format!("Item {}", (oi * 25) + i)),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load(
|
||||
"fonts/FiraSans-Bold.ttf",
|
||||
),
|
||||
|
@ -288,7 +288,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// Title
|
||||
parent.spawn((
|
||||
Text::new("Nested Scrolling Lists"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: FONT_SIZE,
|
||||
..default()
|
||||
|
@ -333,7 +333,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
parent
|
||||
.spawn((
|
||||
Text(format!("Item {}", (oi * 25) + i)),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load(
|
||||
"fonts/FiraSans-Bold.ttf",
|
||||
),
|
||||
|
|
|
@ -42,12 +42,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// ui camera
|
||||
commands.spawn(Camera2d);
|
||||
|
||||
let text_style = TextStyle {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
};
|
||||
let text_font = (
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 33.0,
|
||||
..Default::default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
);
|
||||
|
||||
commands
|
||||
.spawn(NodeBundle {
|
||||
|
@ -75,7 +77,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Size Constraints Example"),
|
||||
text_style.clone(),
|
||||
text_font.clone(),
|
||||
Style {
|
||||
margin: UiRect::bottom(Val::Px(25.)),
|
||||
..Default::default()
|
||||
|
@ -103,7 +105,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
Constraint::Width,
|
||||
Constraint::MaxWidth,
|
||||
] {
|
||||
spawn_button_row(parent, constraint, text_style.clone());
|
||||
spawn_button_row(parent, constraint, text_font.clone());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -150,7 +152,11 @@ fn spawn_bar(parent: &mut ChildBuilder) {
|
|||
});
|
||||
}
|
||||
|
||||
fn spawn_button_row(parent: &mut ChildBuilder, constraint: Constraint, text_style: TextStyle) {
|
||||
fn spawn_button_row(
|
||||
parent: &mut ChildBuilder,
|
||||
constraint: Constraint,
|
||||
text_style: (TextFont, TextColor),
|
||||
) {
|
||||
let label = match constraint {
|
||||
Constraint::FlexBasis => "flex_basis",
|
||||
Constraint::Width => "size",
|
||||
|
@ -229,7 +235,7 @@ fn spawn_button(
|
|||
constraint: Constraint,
|
||||
action: ButtonValue,
|
||||
label: String,
|
||||
text_style: TextStyle,
|
||||
text_style: (TextFont, TextColor),
|
||||
active: bool,
|
||||
) {
|
||||
parent
|
||||
|
@ -271,14 +277,12 @@ fn spawn_button(
|
|||
})
|
||||
.with_child((
|
||||
Text::new(label),
|
||||
TextStyle {
|
||||
color: if active {
|
||||
ACTIVE_TEXT_COLOR
|
||||
} else {
|
||||
UNHOVERED_TEXT_COLOR
|
||||
},
|
||||
..text_style
|
||||
},
|
||||
text_style.0,
|
||||
TextColor(if active {
|
||||
ACTIVE_TEXT_COLOR
|
||||
} else {
|
||||
UNHOVERED_TEXT_COLOR
|
||||
}),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
));
|
||||
});
|
||||
|
@ -290,7 +294,7 @@ fn update_buttons(
|
|||
Changed<Interaction>,
|
||||
>,
|
||||
mut bar_query: Query<&mut Style, With<Bar>>,
|
||||
mut text_query: Query<&mut TextStyle>,
|
||||
mut text_query: Query<&mut TextColor>,
|
||||
children_query: Query<&Children>,
|
||||
mut button_activated_event: EventWriter<ButtonActivatedEvent>,
|
||||
) {
|
||||
|
@ -319,9 +323,9 @@ fn update_buttons(
|
|||
for &child in children {
|
||||
if let Ok(grand_children) = children_query.get(child) {
|
||||
for &grandchild in grand_children {
|
||||
if let Ok(mut style) = text_query.get_mut(grandchild) {
|
||||
if style.color != ACTIVE_TEXT_COLOR {
|
||||
style.color = HOVERED_TEXT_COLOR;
|
||||
if let Ok(mut text_color) = text_query.get_mut(grandchild) {
|
||||
if text_color.0 != ACTIVE_TEXT_COLOR {
|
||||
text_color.0 = HOVERED_TEXT_COLOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -334,9 +338,9 @@ fn update_buttons(
|
|||
for &child in children {
|
||||
if let Ok(grand_children) = children_query.get(child) {
|
||||
for &grandchild in grand_children {
|
||||
if let Ok(mut style) = text_query.get_mut(grandchild) {
|
||||
if style.color != ACTIVE_TEXT_COLOR {
|
||||
style.color = UNHOVERED_TEXT_COLOR;
|
||||
if let Ok(mut text_color) = text_query.get_mut(grandchild) {
|
||||
if text_color.0 != ACTIVE_TEXT_COLOR {
|
||||
text_color.0 = UNHOVERED_TEXT_COLOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -353,14 +357,14 @@ fn update_radio_buttons_colors(
|
|||
button_query: Query<(Entity, &Constraint, &Interaction)>,
|
||||
mut border_query: Query<&mut BorderColor>,
|
||||
mut color_query: Query<&mut BackgroundColor>,
|
||||
mut text_query: Query<&mut TextStyle>,
|
||||
mut text_query: Query<&mut TextColor>,
|
||||
children_query: Query<&Children>,
|
||||
) {
|
||||
for &ButtonActivatedEvent(button_id) in event_reader.read() {
|
||||
let (_, target_constraint, _) = button_query.get(button_id).unwrap();
|
||||
for (id, constraint, interaction) in button_query.iter() {
|
||||
if target_constraint == constraint {
|
||||
let (border_color, inner_color, text_color) = if id == button_id {
|
||||
let (border_color, inner_color, label_color) = if id == button_id {
|
||||
(ACTIVE_BORDER_COLOR, ACTIVE_INNER_COLOR, ACTIVE_TEXT_COLOR)
|
||||
} else {
|
||||
(
|
||||
|
@ -378,8 +382,8 @@ fn update_radio_buttons_colors(
|
|||
for &child in children_query.get(id).into_iter().flatten() {
|
||||
color_query.get_mut(child).unwrap().0 = inner_color;
|
||||
for &grandchild in children_query.get(child).into_iter().flatten() {
|
||||
if let Ok(mut style) = text_query.get_mut(grandchild) {
|
||||
style.color = text_color;
|
||||
if let Ok(mut text_color) = text_query.get_mut(grandchild) {
|
||||
text_color.0 = label_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
commands.spawn((
|
||||
// Accepts a `String` or any type that converts into a `String`, such as `&str`
|
||||
Text::new("hello\nbevy!"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
// This font is loaded and will be used instead of the default font.
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 67.0,
|
||||
|
@ -55,7 +55,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.spawn((
|
||||
// Create a Text with multiple child spans.
|
||||
Text::new("FPS: "),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
// This font is loaded and will be used instead of the default font.
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 42.0,
|
||||
|
@ -65,20 +65,24 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.with_child((
|
||||
TextSpan::default(),
|
||||
if cfg!(feature = "default_font") {
|
||||
TextStyle {
|
||||
font_size: 33.0,
|
||||
color: GOLD.into(),
|
||||
// If no font is specified, the default font (a minimal subset of FiraMono) will be used.
|
||||
..default()
|
||||
}
|
||||
(
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
// If no font is specified, the default font (a minimal subset of FiraMono) will be used.
|
||||
..default()
|
||||
},
|
||||
TextColor(GOLD.into()),
|
||||
)
|
||||
} else {
|
||||
// "default_font" feature is unavailable, load a font to use instead.
|
||||
TextStyle {
|
||||
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 33.0,
|
||||
color: GOLD.into(),
|
||||
..default()
|
||||
}
|
||||
(
|
||||
// "default_font" feature is unavailable, load a font to use instead.
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 33.0,
|
||||
..Default::default()
|
||||
},
|
||||
TextColor(GOLD.into()),
|
||||
)
|
||||
},
|
||||
FpsText,
|
||||
));
|
||||
|
@ -99,7 +103,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
#[cfg(not(feature = "default_font"))]
|
||||
commands.spawn((
|
||||
Text::new("Default font disabled"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
..default()
|
||||
},
|
||||
|
@ -112,12 +116,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
));
|
||||
}
|
||||
|
||||
fn text_color_system(time: Res<Time>, mut query: Query<&mut TextStyle, With<ColorText>>) {
|
||||
for mut style in &mut query {
|
||||
fn text_color_system(time: Res<Time>, mut query: Query<&mut TextColor, With<ColorText>>) {
|
||||
for mut text_color in &mut query {
|
||||
let seconds = time.elapsed_seconds();
|
||||
|
||||
// Update the color of the ColorText span.
|
||||
style.color = Color::srgb(
|
||||
text_color.0 = Color::srgb(
|
||||
ops::sin(1.25 * seconds) / 2.0 + 0.5,
|
||||
ops::sin(0.75 * seconds) / 2.0 + 0.5,
|
||||
ops::sin(0.50 * seconds) / 2.0 + 0.5,
|
||||
|
|
|
@ -60,7 +60,7 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
}).with_children(|builder| {
|
||||
builder.spawn((
|
||||
Text::new("This is\ntext with\nline breaks\nin the top left."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 25.0,
|
||||
..default()
|
||||
|
@ -71,12 +71,12 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
Text::new(
|
||||
"This text is right-justified. The `JustifyText` component controls the horizontal alignment of the lines of multi-line text relative to each other, and does not affect the text node's position in the UI layout.",
|
||||
),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 25.0,
|
||||
color: YELLOW.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(YELLOW.into()),
|
||||
TextLayout::new_with_justify(JustifyText::Right),
|
||||
Style {
|
||||
max_width: Val::Px(300.),
|
||||
|
@ -87,7 +87,7 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
builder.spawn((
|
||||
Text::new(
|
||||
"This\ntext has\nline breaks and also a set width in the bottom left."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 25.0,
|
||||
..default()
|
||||
|
@ -115,12 +115,12 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
|
||||
builder.spawn((Text::new(
|
||||
"This text is very long, has a limited width, is center-justified, is positioned in the top right and is also colored pink."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.8, 0.2, 0.7),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.8, 0.2, 0.7)),
|
||||
TextLayout::new_with_justify(JustifyText::Center),
|
||||
Style {
|
||||
max_width: Val::Px(400.),
|
||||
|
@ -130,12 +130,12 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
|
||||
builder.spawn((Text::new(
|
||||
"This text is left-justified and is vertically positioned to distribute the empty space equally above and below it."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 29.0,
|
||||
color: YELLOW.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(YELLOW.into()),
|
||||
TextLayout::new_with_justify(JustifyText::Left),
|
||||
Style {
|
||||
max_width: Val::Px(300.),
|
||||
|
@ -146,13 +146,13 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
|
||||
builder.spawn((
|
||||
Text::new("This text is fully justified and is positioned in the same way."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 29.0,
|
||||
color: GREEN_YELLOW.into(),
|
||||
..default()
|
||||
},
|
||||
TextLayout::new_with_justify(JustifyText::Justified),
|
||||
TextColor(GREEN_YELLOW.into()),
|
||||
Style {
|
||||
max_width: Val::Px(300.),
|
||||
..default()
|
||||
|
@ -163,7 +163,7 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
|
||||
builder.spawn((
|
||||
Text::default(),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 21.0,
|
||||
..default()
|
||||
|
@ -174,7 +174,7 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.with_children(|p| {
|
||||
p.spawn((
|
||||
TextSpan::new("\nThis text changes in the bottom right"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 21.0,
|
||||
..default()
|
||||
|
@ -182,66 +182,66 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
));
|
||||
p.spawn((
|
||||
TextSpan::new(" this text has zero fontsize"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 0.0,
|
||||
color: BLUE.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(BLUE.into()),
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan::new("\nThis text changes in the bottom right - "),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 21.0,
|
||||
color: RED.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(RED.into()),
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan::default(),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 21.0,
|
||||
color: ORANGE_RED.into(),
|
||||
..default()
|
||||
}
|
||||
},
|
||||
TextColor(ORANGE_RED.into()),
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan::new(" fps, "),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 10.0,
|
||||
color: YELLOW.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(YELLOW.into()),
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan::default(),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 21.0,
|
||||
color: LIME.into(),
|
||||
..default()
|
||||
}
|
||||
},
|
||||
TextColor(LIME.into()),
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan::new(" ms/frame"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: 42.0,
|
||||
color: BLUE.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(BLUE.into()),
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan::new(" this text has negative fontsize"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font.clone(),
|
||||
font_size: -42.0,
|
||||
color: BLUE.into(),
|
||||
..default()
|
||||
},
|
||||
TextColor(BLUE.into()),
|
||||
));
|
||||
});
|
||||
})
|
||||
|
|
|
@ -45,7 +45,7 @@ fn main() {
|
|||
fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
commands.spawn(Camera2d);
|
||||
|
||||
let text_style = TextStyle {
|
||||
let text_font = TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 12.0,
|
||||
..default()
|
||||
|
@ -121,7 +121,7 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
for (j, message) in messages.into_iter().enumerate() {
|
||||
commands.entity(column_id).with_child((
|
||||
Text(message.clone()),
|
||||
text_style.clone(),
|
||||
text_font.clone(),
|
||||
TextLayout::new(JustifyText::Left, linebreak),
|
||||
BackgroundColor(Color::srgb(0.8 - j as f32 * 0.2, 0., 0.)),
|
||||
));
|
||||
|
|
|
@ -43,13 +43,13 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Button 1"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font_handle.clone(),
|
||||
font_size: 33.0,
|
||||
// Alpha channel of the color controls transparency.
|
||||
color: Color::srgba(1.0, 1.0, 1.0, 0.2),
|
||||
..default()
|
||||
},
|
||||
// Alpha channel of the color controls transparency.
|
||||
TextColor(Color::srgba(1.0, 1.0, 1.0, 0.2)),
|
||||
));
|
||||
});
|
||||
|
||||
|
@ -70,13 +70,13 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Button 2"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: font_handle.clone(),
|
||||
font_size: 33.0,
|
||||
// Alpha channel of the color controls transparency.
|
||||
color: Color::srgba(1.0, 1.0, 1.0, 0.2),
|
||||
..default()
|
||||
},
|
||||
// Alpha channel of the color controls transparency.
|
||||
TextColor(Color::srgba(1.0, 1.0, 1.0, 0.2)),
|
||||
));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -75,7 +75,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// text
|
||||
parent.spawn((
|
||||
Text::new("Text Example"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 25.0,
|
||||
..default()
|
||||
|
@ -90,7 +90,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// Debug overlay text
|
||||
parent.spawn((
|
||||
Text::new("Press Space to enable debug outlines."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
..default()
|
||||
},
|
||||
|
@ -100,7 +100,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
#[cfg(not(feature = "bevy_dev_tools"))]
|
||||
parent.spawn((
|
||||
Text::new("Try enabling feature \"bevy_dev_tools\"."),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
..default()
|
||||
},
|
||||
|
@ -124,7 +124,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// Title
|
||||
parent.spawn((
|
||||
Text::new("Scrolling list"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 21.,
|
||||
..default()
|
||||
|
@ -150,7 +150,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
parent
|
||||
.spawn((
|
||||
Text(format!("Item {i}")),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -23,9 +23,8 @@ fn main() {
|
|||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
commands.spawn(Camera2d);
|
||||
|
||||
let text_style = TextStyle {
|
||||
let text_font = TextFont {
|
||||
font_size: 13.,
|
||||
color: Color::BLACK,
|
||||
..default()
|
||||
};
|
||||
|
||||
|
@ -56,7 +55,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
..default()
|
||||
})
|
||||
.with_children(|parent| {
|
||||
parent.spawn((Text::new("Size!"), text_style));
|
||||
parent.spawn((Text::new("Size!"), text_font, TextColor::BLACK));
|
||||
});
|
||||
parent.spawn(NodeBundle {
|
||||
style: Style {
|
||||
|
|
|
@ -25,7 +25,7 @@ fn setup(
|
|||
// Camera
|
||||
commands.spawn(Camera2d);
|
||||
|
||||
let text_style = TextStyle::default();
|
||||
let text_font = TextFont::default();
|
||||
|
||||
let texture_handle = asset_server.load("textures/rpg/chars/gabe/gabe-idle-run.png");
|
||||
let texture_atlas = TextureAtlasLayout::from_grid(UVec2::splat(24), 7, 1, None, None);
|
||||
|
@ -40,7 +40,7 @@ fn setup(
|
|||
flex_direction: FlexDirection::Column,
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
row_gap: Val::Px(text_style.font_size * 2.),
|
||||
row_gap: Val::Px(text_font.font_size * 2.),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
|
@ -61,15 +61,13 @@ fn setup(
|
|||
Outline::new(Val::Px(8.0), Val::ZERO, CRIMSON.into()),
|
||||
));
|
||||
parent
|
||||
.spawn((Text::new("press "), text_style.clone()))
|
||||
.spawn((Text::new("press "), text_font.clone()))
|
||||
.with_child((
|
||||
TextSpan::new("space"),
|
||||
TextStyle {
|
||||
color: YELLOW.into(),
|
||||
..text_style.clone()
|
||||
},
|
||||
TextColor(YELLOW.into()),
|
||||
text_font.clone(),
|
||||
))
|
||||
.with_child((TextSpan::new(" to advance frames"), text_style));
|
||||
.with_child((TextSpan::new(" to advance frames"), text_font));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -104,12 +104,12 @@ fn setup(
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Button"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -88,12 +88,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Text::new("Button"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 33.0,
|
||||
color: Color::srgb(0.9, 0.9, 0.9),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
commands.spawn((
|
||||
// Accepts a `String` or any type that converts into a `String`, such as `&str`
|
||||
Text::new("Hit 'P' then scroll/click around!"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 83.0, // Nice and big so you can see it!
|
||||
..default()
|
||||
|
|
|
@ -200,27 +200,9 @@ pub(crate) mod test_setup {
|
|||
))
|
||||
.with_children(|p| {
|
||||
p.spawn(TextSpan::new("Press space bar to cycle modes\n"));
|
||||
p.spawn((
|
||||
TextSpan::default(),
|
||||
TextStyle {
|
||||
color: LIME.into(),
|
||||
..default()
|
||||
},
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan::new("\nFrame: "),
|
||||
TextStyle {
|
||||
color: YELLOW.into(),
|
||||
..default()
|
||||
},
|
||||
));
|
||||
p.spawn((
|
||||
TextSpan::new(""),
|
||||
TextStyle {
|
||||
color: YELLOW.into(),
|
||||
..default()
|
||||
},
|
||||
));
|
||||
p.spawn((TextSpan::default(), TextColor(LIME.into())));
|
||||
p.spawn((TextSpan::new("\nFrame: "), TextColor(YELLOW.into())));
|
||||
p.spawn((TextSpan::new(""), TextColor(YELLOW.into())));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ fn setup(mut commands: Commands) {
|
|||
.with_child((
|
||||
CustomText,
|
||||
Text::new("Example text"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 25.0,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -45,7 +45,7 @@ fn setup_ui(mut commands: Commands) {
|
|||
// Text where we display current resolution
|
||||
.with_child((
|
||||
Text::new("Resolution"),
|
||||
TextStyle {
|
||||
TextFont {
|
||||
font_size: 42.0,
|
||||
..default()
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue