diff --git a/crates/bevy_color/src/oklaba.rs b/crates/bevy_color/src/oklaba.rs index 4da4c805fb97c..5501e8e4c6ec8 100644 --- a/crates/bevy_color/src/oklaba.rs +++ b/crates/bevy_color/src/oklaba.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)] #[reflect(PartialEq, Serialize, Deserialize, Default)] pub struct Oklaba { - /// The 'l' channel. [0.0, 1.0] + /// The 'lightness' channel. [0.0, 1.0] pub lightness: f32, /// The 'a' channel. [-1.0, 1.0] pub a: f32, @@ -61,7 +61,7 @@ impl Oklaba { } } - /// Return a copy of this color with the 'l' channel set to the given value. + /// Return a copy of this color with the 'lightness' channel set to the given value. pub const fn with_lightness(self, lightness: f32) -> Self { Self { lightness, ..self } } diff --git a/crates/bevy_color/src/oklcha.rs b/crates/bevy_color/src/oklcha.rs index 4185990e5d416..133794e256b35 100644 --- a/crates/bevy_color/src/oklcha.rs +++ b/crates/bevy_color/src/oklcha.rs @@ -56,17 +56,17 @@ impl Oklcha { } /// Return a copy of this color with the 'lightness' channel set to the given value. - pub const fn with_l(self, lightness: f32) -> Self { + pub const fn with_lightness(self, lightness: f32) -> Self { Self { lightness, ..self } } /// Return a copy of this color with the 'chroma' channel set to the given value. - pub const fn with_c(self, chroma: f32) -> Self { + pub const fn with_chroma(self, chroma: f32) -> Self { Self { chroma, ..self } } /// Return a copy of this color with the 'hue' channel set to the given value. - pub const fn with_h(self, hue: f32) -> Self { + pub const fn with_hue(self, hue: f32) -> Self { Self { hue, ..self } } diff --git a/crates/bevy_dev_tools/src/fps_overlay.rs b/crates/bevy_dev_tools/src/fps_overlay.rs index 51b8e7886dcf9..d3f57f998411b 100644 --- a/crates/bevy_dev_tools/src/fps_overlay.rs +++ b/crates/bevy_dev_tools/src/fps_overlay.rs @@ -10,8 +10,18 @@ use bevy_ecs::{ schedule::{common_conditions::resource_changed, IntoSystemConfigs}, system::{Commands, Query, Res, Resource}, }; +use bevy_hierarchy::BuildChildren; use bevy_text::{Font, Text, TextSection, TextStyle}; -use bevy_ui::node_bundles::TextBundle; +use bevy_ui::{ + node_bundles::{NodeBundle, TextBundle}, + PositionType, Style, ZIndex, +}; +use bevy_utils::default; + +/// Global [`ZIndex`] used to render the fps overlay. +/// +/// We use a number slightly under `i32::MAX` so you can render on top of it if you really need to. +pub const FPS_OVERLAY_ZINDEX: i32 = i32::MAX - 32; /// A plugin that adds an FPS overlay to the Bevy application. /// @@ -67,13 +77,26 @@ impl Default for FpsOverlayConfig { struct FpsText; fn setup(mut commands: Commands, overlay_config: Res) { - commands.spawn(( - TextBundle::from_sections([ - TextSection::new("FPS: ", overlay_config.text_config.clone()), - TextSection::from_style(overlay_config.text_config.clone()), - ]), - FpsText, - )); + commands + .spawn(NodeBundle { + style: Style { + // We need to make sure the overlay doesn't affect the position of other UI nodes + position_type: PositionType::Absolute, + ..default() + }, + // Render overlay on top of everything + z_index: ZIndex::Global(FPS_OVERLAY_ZINDEX), + ..default() + }) + .with_children(|c| { + c.spawn(( + TextBundle::from_sections([ + TextSection::new("FPS: ", overlay_config.text_config.clone()), + TextSection::from_style(overlay_config.text_config.clone()), + ]), + FpsText, + )); + }); } fn update_text(diagnostic: Res, mut query: Query<&mut Text, With>) { diff --git a/crates/bevy_math/src/direction.rs b/crates/bevy_math/src/direction.rs index a88d44b6024a4..150a9105b86e1 100644 --- a/crates/bevy_math/src/direction.rs +++ b/crates/bevy_math/src/direction.rs @@ -151,6 +151,12 @@ impl TryFrom for Dir2 { } } +impl From for Vec2 { + fn from(value: Dir2) -> Self { + value.as_vec2() + } +} + impl std::ops::Deref for Dir2 { type Target = Vec2; fn deref(&self) -> &Self::Target { diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index ca22a773dc767..728a863b703cf 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -88,7 +88,7 @@ pub struct ComputedCameraValues { /// /// #[derive(Component, Clone, Copy, Reflect)] -#[reflect_value(Component)] +#[reflect_value(Component, Default)] pub struct Exposure { /// pub ev100: f32, @@ -184,7 +184,7 @@ impl Default for PhysicalCameraParameters { /// Adding a camera is typically done by adding a bundle, either the `Camera2dBundle` or the /// `Camera3dBundle`. #[derive(Component, Debug, Reflect, Clone)] -#[reflect(Component)] +#[reflect(Component, Default)] pub struct Camera { /// If set, this camera will render to the given [`Viewport`] rectangle within the configured [`RenderTarget`]. pub viewport: Option, @@ -771,7 +771,7 @@ pub fn camera_system( /// This component lets you control the [`TextureUsages`] field of the main texture generated for the camera #[derive(Component, ExtractComponent, Clone, Copy, Reflect)] -#[reflect_value(Component)] +#[reflect_value(Component, Default)] pub struct CameraMainTextureUsages(pub TextureUsages); impl Default for CameraMainTextureUsages { fn default() -> Self { diff --git a/crates/bevy_render/src/camera/clear_color.rs b/crates/bevy_render/src/camera/clear_color.rs index 02b74ce46c1a3..e986b3d30b29a 100644 --- a/crates/bevy_render/src/camera/clear_color.rs +++ b/crates/bevy_render/src/camera/clear_color.rs @@ -2,12 +2,12 @@ use crate::extract_resource::ExtractResource; use bevy_color::Color; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::prelude::*; -use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; +use bevy_reflect::prelude::*; use serde::{Deserialize, Serialize}; /// For a camera, specifies the color used to clear the viewport before rendering. #[derive(Reflect, Serialize, Deserialize, Clone, Debug, Default)] -#[reflect(Serialize, Deserialize)] +#[reflect(Serialize, Deserialize, Default)] pub enum ClearColorConfig { /// The clear color is taken from the world's [`ClearColor`] resource. #[default] @@ -31,7 +31,7 @@ impl From for ClearColorConfig { /// This color appears as the "background" color for simple apps, /// when there are portions of the screen with nothing rendered. #[derive(Resource, Clone, Debug, Deref, DerefMut, ExtractResource, Reflect)] -#[reflect(Resource)] +#[reflect(Resource, Default)] pub struct ClearColor(pub Color); /// Match the dark gray bevy website code block color by default. diff --git a/crates/bevy_render/src/globals.rs b/crates/bevy_render/src/globals.rs index d1a7df0b5e31a..11f0c5295efff 100644 --- a/crates/bevy_render/src/globals.rs +++ b/crates/bevy_render/src/globals.rs @@ -9,7 +9,7 @@ use bevy_app::{App, Plugin}; use bevy_asset::{load_internal_asset, Handle}; use bevy_core::FrameCount; use bevy_ecs::prelude::*; -use bevy_reflect::Reflect; +use bevy_reflect::prelude::*; use bevy_time::Time; pub const GLOBALS_TYPE_HANDLE: Handle = Handle::weak_from_u128(17924628719070609599); @@ -45,7 +45,7 @@ fn extract_time(mut commands: Commands, time: Extract>) { /// Contains global values useful when writing shaders. /// Currently only contains values related to time. #[derive(Default, Clone, Resource, ExtractResource, Reflect, ShaderType)] -#[reflect(Resource)] +#[reflect(Resource, Default)] pub struct GlobalsUniform { /// The time since startup in seconds. /// Wraps to 0 after 1 hour. diff --git a/crates/bevy_render/src/mesh/mesh/skinning.rs b/crates/bevy_render/src/mesh/mesh/skinning.rs index 616f2a5472abf..f1605ec74b735 100644 --- a/crates/bevy_render/src/mesh/mesh/skinning.rs +++ b/crates/bevy_render/src/mesh/mesh/skinning.rs @@ -6,11 +6,11 @@ use bevy_ecs::{ reflect::ReflectMapEntities, }; use bevy_math::Mat4; -use bevy_reflect::{Reflect, TypePath}; +use bevy_reflect::prelude::*; use std::ops::Deref; #[derive(Component, Debug, Default, Clone, Reflect)] -#[reflect(Component, MapEntities)] +#[reflect(Component, MapEntities, Default)] pub struct SkinnedMesh { pub inverse_bindposes: Handle, pub joints: Vec, diff --git a/crates/bevy_render/src/mesh/morph.rs b/crates/bevy_render/src/mesh/morph.rs index 74430beffc7c8..b5eac7cdfec63 100644 --- a/crates/bevy_render/src/mesh/morph.rs +++ b/crates/bevy_render/src/mesh/morph.rs @@ -9,7 +9,7 @@ use bevy_asset::Handle; use bevy_ecs::prelude::*; use bevy_hierarchy::Children; use bevy_math::Vec3; -use bevy_reflect::Reflect; +use bevy_reflect::prelude::*; use bytemuck::{Pod, Zeroable}; use std::{iter, mem}; use thiserror::Error; @@ -128,7 +128,7 @@ impl MorphTargetImage { /// /// [morph targets]: https://en.wikipedia.org/wiki/Morph_target_animation #[derive(Reflect, Default, Debug, Clone, Component)] -#[reflect(Debug, Component)] +#[reflect(Debug, Component, Default)] pub struct MorphWeights { weights: Vec, /// The first mesh primitive assigned to these weights @@ -173,7 +173,7 @@ impl MorphWeights { /// /// [morph targets]: https://en.wikipedia.org/wiki/Morph_target_animation #[derive(Reflect, Default, Debug, Clone, Component)] -#[reflect(Debug, Component)] +#[reflect(Debug, Component, Default)] pub struct MeshMorphWeights { weights: Vec, } diff --git a/crates/bevy_render/src/primitives/mod.rs b/crates/bevy_render/src/primitives/mod.rs index 25fef4abd2c09..d5796b4a7ff70 100644 --- a/crates/bevy_render/src/primitives/mod.rs +++ b/crates/bevy_render/src/primitives/mod.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; use bevy_ecs::{component::Component, entity::EntityHashMap, reflect::ReflectComponent}; use bevy_math::{Affine3A, Mat3A, Mat4, Vec3, Vec3A, Vec4, Vec4Swizzles}; -use bevy_reflect::Reflect; +use bevy_reflect::prelude::*; /// An axis-aligned bounding box, defined by: /// - a center, @@ -31,7 +31,7 @@ use bevy_reflect::Reflect; /// [`Mesh`]: crate::mesh::Mesh /// [`Handle`]: crate::mesh::Mesh #[derive(Component, Clone, Copy, Debug, Default, Reflect, PartialEq)] -#[reflect(Component)] +#[reflect(Component, Default)] pub struct Aabb { pub center: Vec3A, pub half_extents: Vec3A, @@ -212,7 +212,7 @@ impl HalfSpace { /// [`CameraProjection`]: crate::camera::CameraProjection /// [`GlobalTransform`]: bevy_transform::components::GlobalTransform #[derive(Component, Clone, Copy, Debug, Default, Reflect)] -#[reflect(Component)] +#[reflect(Component, Default)] pub struct Frustum { #[reflect(ignore)] pub half_spaces: [HalfSpace; 6], @@ -303,7 +303,7 @@ impl Frustum { } #[derive(Component, Clone, Debug, Default, Reflect)] -#[reflect(Component)] +#[reflect(Component, Default)] pub struct CubemapFrusta { #[reflect(ignore)] pub frusta: [Frustum; 6], @@ -319,7 +319,7 @@ impl CubemapFrusta { } #[derive(Component, Debug, Default, Reflect)] -#[reflect(Component)] +#[reflect(Component, Default)] pub struct CascadesFrusta { #[reflect(ignore)] pub frusta: EntityHashMap>, diff --git a/crates/bevy_render/src/texture/image.rs b/crates/bevy_render/src/texture/image.rs index b052519b056f6..d163841837c03 100644 --- a/crates/bevy_render/src/texture/image.rs +++ b/crates/bevy_render/src/texture/image.rs @@ -15,7 +15,7 @@ use bevy_asset::Asset; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::system::{lifetimeless::SRes, Resource, SystemParamItem}; use bevy_math::{AspectRatio, UVec2, Vec2}; -use bevy_reflect::Reflect; +use bevy_reflect::prelude::*; use serde::{Deserialize, Serialize}; use std::hash::Hash; use thiserror::Error; @@ -112,7 +112,7 @@ impl ImageFormat { } #[derive(Asset, Reflect, Debug, Clone)] -#[reflect_value] +#[reflect_value(Default)] pub struct Image { pub data: Vec, // TODO: this nesting makes accessing Image metadata verbose. Either flatten out descriptor or add accessors diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 444888b569ad0..3b888e33e69dd 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -90,7 +90,7 @@ impl Plugin for ViewPlugin { #[derive( Resource, Default, Clone, Copy, ExtractResource, Reflect, PartialEq, PartialOrd, Debug, )] -#[reflect(Resource)] +#[reflect(Resource, Default)] pub enum Msaa { Off = 1, Sample2 = 2, diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index c674a36829e05..50ea668f14c7c 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -168,7 +168,7 @@ pub struct NoFrustumCulling; /// This component is intended to be attached to the same entity as the [`Camera`] and /// the [`Frustum`] defining the view. #[derive(Clone, Component, Default, Debug, Reflect)] -#[reflect(Component)] +#[reflect(Component, Default)] pub struct VisibleEntities { #[reflect(ignore)] pub entities: Vec, diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 2ade33e359a52..49b3fb1ad979a 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -9,7 +9,6 @@ use bevy_core_pipeline::{core_2d::Camera2d, core_3d::Camera3d}; use bevy_hierarchy::Parent; use bevy_render::{render_phase::PhaseItem, view::ViewVisibility, ExtractSchedule, Render}; use bevy_sprite::{SpriteAssetEvents, TextureAtlas}; -use bevy_window::{PrimaryWindow, Window}; pub use pipeline::*; pub use render_pass::*; pub use ui_material_pipeline::*; @@ -181,7 +180,7 @@ pub struct ExtractedUiNodes { pub fn extract_uinode_background_colors( mut extracted_uinodes: ResMut, - windows: Extract>>, + camera_query: Extract>, default_ui_camera: Extract, ui_scale: Extract>, uinode_query: Extract< @@ -193,16 +192,10 @@ pub fn extract_uinode_background_colors( Option<&CalculatedClip>, Option<&TargetCamera>, &BackgroundColor, - &BorderRadius, + Option<&BorderRadius>, )>, >, ) { - let viewport_size = windows - .get_single() - .map(|window| window.resolution.size()) - .unwrap_or(Vec2::ZERO) - * ui_scale.0; - for ( entity, uinode, @@ -224,8 +217,25 @@ pub fn extract_uinode_background_colors( continue; } - let border_radius = - resolve_border_radius(border_radius, uinode.size(), viewport_size, ui_scale.0); + let ui_logical_viewport_size = camera_query + .get(camera_entity) + .ok() + .and_then(|(_, c)| c.logical_viewport_size()) + .unwrap_or(Vec2::ZERO) + // The logical window resolution returned by `Window` only takes into account the window scale factor and not `UiScale`, + // so we have to divide by `UiScale` to get the size of the UI viewport. + / ui_scale.0; + + let border_radius = if let Some(border_radius) = border_radius { + resolve_border_radius( + border_radius, + uinode.size(), + ui_logical_viewport_size, + ui_scale.0, + ) + } else { + [0.; 4] + }; extracted_uinodes.uinodes.insert( entity, @@ -254,7 +264,7 @@ pub fn extract_uinode_background_colors( pub fn extract_uinode_images( mut commands: Commands, mut extracted_uinodes: ResMut, - windows: Extract>>, + camera_query: Extract>, texture_atlases: Extract>>, ui_scale: Extract>, default_ui_camera: Extract, @@ -268,16 +278,10 @@ pub fn extract_uinode_images( &UiImage, Option<&TextureAtlas>, Option<&ComputedTextureSlices>, - &BorderRadius, + Option<&BorderRadius>, )>, >, ) { - let viewport_size = windows - .get_single() - .map(|window| window.resolution.size()) - .unwrap_or(Vec2::ZERO) - * ui_scale.0; - for (uinode, transform, view_visibility, clip, camera, image, atlas, slices, border_radius) in &uinode_query { @@ -323,8 +327,25 @@ pub fn extract_uinode_images( ), }; - let border_radius = - resolve_border_radius(border_radius, uinode.size(), viewport_size, ui_scale.0); + let ui_logical_viewport_size = camera_query + .get(camera_entity) + .ok() + .and_then(|(_, c)| c.logical_viewport_size()) + .unwrap_or(Vec2::ZERO) + // The logical window resolution returned by `Window` only takes into account the window scale factor and not `UiScale`, + // so we have to divide by `UiScale` to get the size of the UI viewport. + / ui_scale.0; + + let border_radius = if let Some(border_radius) = border_radius { + resolve_border_radius( + border_radius, + uinode.size(), + ui_logical_viewport_size, + ui_scale.0, + ) + } else { + [0.; 4] + }; extracted_uinodes.uinodes.insert( commands.spawn_empty().id(), diff --git a/crates/bevy_ui/src/render/ui.wgsl b/crates/bevy_ui/src/render/ui.wgsl index 7a73382a650ce..bb312713c5c03 100644 --- a/crates/bevy_ui/src/render/ui.wgsl +++ b/crates/bevy_ui/src/render/ui.wgsl @@ -300,12 +300,12 @@ fn draw(in: VertexOutput) -> vec4 { // is present, otherwise an outline about the external boundary would be drawn even without // a border. let t = 1. - select(step(0.0, border_distance), smoothstep(0.0, fborder, border_distance), external_distance < internal_distance); - return vec4(color.rgb * t * color.a, t * color.a); + return color.rgba * t; } // The item is a rectangle, draw normally with anti-aliasing at the edges. let t = 1. - smoothstep(0.0, fexternal, external_distance); - return vec4(color.rgb * t * color.a, t * color.a); + return color.rgba * t; } @fragment diff --git a/examples/dev_tools/fps_overlay.rs b/examples/dev_tools/fps_overlay.rs index e7f4cada95462..a2718ecc3c5c0 100644 --- a/examples/dev_tools/fps_overlay.rs +++ b/examples/dev_tools/fps_overlay.rs @@ -28,30 +28,33 @@ fn main() { } fn setup(mut commands: Commands) { - // We need to spawn camera to see overlay + // We need to spawn a camera (2d or 3d) to see the overlay commands.spawn(Camera2dBundle::default()); - commands.spawn( - TextBundle::from_sections([ - TextSection::new( - "Press 1 to change color of the overlay.", - TextStyle { - font_size: 25.0, - ..default() - }, - ), - TextSection::new( - "\nPress 2 to change size of the overlay", + + // Instruction text + commands + .spawn(NodeBundle { + style: Style { + width: Val::Percent(100.0), + height: Val::Percent(100.0), + align_items: AlignItems::Center, + justify_content: JustifyContent::Center, + ..default() + }, + ..default() + }) + .with_children(|c| { + c.spawn(TextBundle::from_section( + concat!( + "Press 1 to change color of the overlay.\n", + "Press 2 to change size of the overlay." + ), TextStyle { font_size: 25.0, ..default() }, - ), - ]) - .with_style(Style { - justify_self: JustifySelf::Center, - ..default() - }), - ); + )); + }); } fn customize_config(input: Res>, mut overlay: ResMut) {