Merge branch 'main' into ignore_transparancy_on_sprite_picking

This commit is contained in:
Michael Walter Van Der Velden 2024-11-22 21:45:31 +00:00 committed by GitHub
commit 50e862d1ad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 141 additions and 46 deletions

View file

@ -116,7 +116,6 @@ default = [
"bevy_mesh_picking_backend",
"bevy_pbr",
"bevy_picking",
"bevy_remote",
"bevy_render",
"bevy_scene",
"bevy_sprite",
@ -141,13 +140,22 @@ default = [
]
# Provides an implementation for picking meshes
bevy_mesh_picking_backend = ["bevy_picking"]
bevy_mesh_picking_backend = [
"bevy_picking",
"bevy_internal/bevy_mesh_picking_backend",
]
# Provides an implementation for picking sprites
bevy_sprite_picking_backend = ["bevy_picking"]
bevy_sprite_picking_backend = [
"bevy_picking",
"bevy_internal/bevy_sprite_picking_backend",
]
# Provides an implementation for picking ui
bevy_ui_picking_backend = ["bevy_picking"]
# Provides an implementation for picking UI
bevy_ui_picking_backend = [
"bevy_picking",
"bevy_internal/bevy_ui_picking_backend",
]
# Force dynamic linking, which improves iterative compile times
dynamic_linking = ["dep:bevy_dylib", "bevy_internal/dynamic_linking"]
@ -3647,6 +3655,7 @@ wasm = true
name = "client"
path = "examples/remote/client.rs"
doc-scrape-examples = true
required-features = ["bevy_remote"]
[package.metadata.example.client]
name = "client"
@ -3658,6 +3667,7 @@ wasm = false
name = "server"
path = "examples/remote/server.rs"
doc-scrape-examples = true
required-features = ["bevy_remote"]
[package.metadata.example.server]
name = "server"

View file

@ -14,7 +14,9 @@ bevy_app = { path = "../crates/bevy_app" }
bevy_ecs = { path = "../crates/bevy_ecs", features = ["multi_threaded"] }
bevy_hierarchy = { path = "../crates/bevy_hierarchy" }
bevy_math = { path = "../crates/bevy_math" }
bevy_picking = { path = "../crates/bevy_picking", features = ["bevy_mesh"] }
bevy_picking = { path = "../crates/bevy_picking", features = [
"bevy_mesh_picking_backend",
] }
bevy_reflect = { path = "../crates/bevy_reflect", features = ["functions"] }
bevy_render = { path = "../crates/bevy_render" }
bevy_tasks = { path = "../crates/bevy_tasks" }

View file

@ -300,6 +300,7 @@ impl AnimationEvent {
}
#[derive(Reflect, Clone)]
#[reflect(opaque)]
struct AnimationEventFn(Arc<dyn Fn(&mut Commands, Entity, f32, f32) + Send + Sync>);
impl Default for AnimationEventFn {

View file

@ -944,19 +944,19 @@ impl Image {
let pixel_size = self.texture_descriptor.format.pixel_size();
let pixel_offset = match self.texture_descriptor.dimension {
TextureDimension::D3 => {
if coords.x > width || coords.y > height || coords.z > depth {
if coords.x >= width || coords.y >= height || coords.z >= depth {
return None;
}
coords.z * height * width + coords.y * width + coords.x
}
TextureDimension::D2 => {
if coords.x > width || coords.y > height {
if coords.x >= width || coords.y >= height {
return None;
}
coords.y * width + coords.x
}
TextureDimension::D1 => {
if coords.x > width {
if coords.x >= width {
return None;
}
coords.x
@ -1573,4 +1573,28 @@ mod test {
assert_eq!(UVec2::ONE, image.size());
assert_eq!(Vec2::ONE, image.size_f32());
}
#[test]
fn on_edge_pixel_is_invalid() {
let image = Image::new_fill(
Extent3d {
width: 5,
height: 10,
depth_or_array_layers: 1,
},
TextureDimension::D2,
&[0, 0, 0, 255],
TextureFormat::Rgba8Unorm,
RenderAssetUsages::MAIN_WORLD,
);
assert!(matches!(image.get_color_at(4, 9), Ok(Color::BLACK)));
assert!(matches!(
image.get_color_at(0, 10),
Err(TextureAccessError::OutOfBounds { x: 0, y: 10, z: 0 })
));
assert!(matches!(
image.get_color_at(5, 10),
Err(TextureAccessError::OutOfBounds { x: 5, y: 10, z: 0 })
));
}
}

View file

@ -218,13 +218,23 @@ bevy_dev_tools = ["dep:bevy_dev_tools"]
bevy_remote = ["dep:bevy_remote"]
# Provides picking functionality
bevy_picking = [
"dep:bevy_picking",
"bevy_picking/bevy_mesh",
"bevy_ui?/bevy_picking",
"bevy_sprite?/bevy_picking",
bevy_picking = ["dep:bevy_picking"]
# Provides a mesh picking backend
bevy_mesh_picking_backend = [
"bevy_picking",
"bevy_picking/bevy_mesh_picking_backend",
]
# Provides a sprite picking backend
bevy_sprite_picking_backend = [
"bevy_picking",
"bevy_sprite/bevy_sprite_picking_backend",
]
# Provides a UI picking backend
bevy_ui_picking_backend = ["bevy_picking", "bevy_ui/bevy_ui_picking_backend"]
# Enable support for the ios_simulator by downgrading some rendering capabilities
ios_simulator = ["bevy_pbr?/ios_simulator", "bevy_render?/ios_simulator"]

View file

@ -45,31 +45,31 @@ impl AspectRatio {
/// Returns the aspect ratio as a f32 value.
#[inline]
pub fn ratio(&self) -> f32 {
pub const fn ratio(&self) -> f32 {
self.0
}
/// Returns the inverse of this aspect ratio (height/width).
#[inline]
pub fn inverse(&self) -> Self {
pub const fn inverse(&self) -> Self {
Self(1.0 / self.0)
}
/// Returns true if the aspect ratio represents a landscape orientation.
#[inline]
pub fn is_landscape(&self) -> bool {
pub const fn is_landscape(&self) -> bool {
self.0 > 1.0
}
/// Returns true if the aspect ratio represents a portrait orientation.
#[inline]
pub fn is_portrait(&self) -> bool {
pub const fn is_portrait(&self) -> bool {
self.0 < 1.0
}
/// Returns true if the aspect ratio is exactly square.
#[inline]
pub fn is_square(&self) -> bool {
pub const fn is_square(&self) -> bool {
self.0 == 1.0
}
}

View file

@ -350,7 +350,7 @@ impl Rot2 {
#[inline]
#[must_use]
#[doc(alias = "conjugate")]
pub fn inverse(self) -> Self {
pub const fn inverse(self) -> Self {
Self {
cos: self.cos,
sin: -self.sin,

View file

@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
[features]
# Provides a mesh picking backend
bevy_mesh = ["dep:bevy_mesh", "dep:crossbeam-channel"]
bevy_mesh_picking_backend = ["dep:bevy_mesh", "dep:crossbeam-channel"]
[dependencies]
bevy_app = { path = "../bevy_app", version = "0.15.0-dev" }

View file

@ -156,7 +156,7 @@ pub mod backend;
pub mod events;
pub mod focus;
pub mod input;
#[cfg(feature = "bevy_mesh")]
#[cfg(feature = "bevy_mesh_picking_backend")]
pub mod mesh_picking;
pub mod pointer;
@ -168,7 +168,7 @@ use bevy_reflect::prelude::*;
///
/// This includes the most common types in this crate, re-exported for your convenience.
pub mod prelude {
#[cfg(feature = "bevy_mesh")]
#[cfg(feature = "bevy_mesh_picking_backend")]
#[doc(hidden)]
pub use crate::mesh_picking::{
ray_cast::{MeshRayCast, RayCastBackfaces, RayCastSettings, RayCastVisibility},

View file

@ -117,7 +117,7 @@ impl Plugin for SyncWorldPlugin {
///
/// [`ExtractComponentPlugin`]: crate::extract_component::ExtractComponentPlugin
/// [`SyncComponentPlugin`]: crate::sync_component::SyncComponentPlugin
#[derive(Component, Clone, Debug, Default, Reflect)]
#[derive(Component, Copy, Clone, Debug, Default, Reflect)]
#[reflect[Component]]
#[component(storage = "SparseSet")]
pub struct SyncToRenderWorld;
@ -165,8 +165,7 @@ pub type MainEntityHashMap<V> = hashbrown::HashMap<MainEntity, V, EntityHash>;
pub type MainEntityHashSet = hashbrown::HashSet<MainEntity, EntityHash>;
/// Marker component that indicates that its entity needs to be despawned at the end of the frame.
#[derive(Component, Clone, Debug, Default, Reflect)]
#[component(storage = "SparseSet")]
#[derive(Component, Copy, Clone, Debug, Default, Reflect)]
pub struct TemporaryRenderEntity;
/// A record enum to what entities with [`SyncToRenderWorld`] have been added or removed.

View file

@ -12,6 +12,7 @@ use bevy_ecs::{
entity::{Entity, EntityHashMap},
query::{Changed, With},
reflect::ReflectComponent,
removal_detection::RemovedComponents,
schedule::IntoSystemConfigs as _,
system::{Query, Res, ResMut, Resource},
};
@ -111,7 +112,7 @@ impl Plugin for VisibilityRangePlugin {
/// that the `end_margin` of a higher LOD is always identical to the
/// `start_margin` of the next lower LOD; this is important for the crossfade
/// effect to function properly.
#[derive(Component, Clone, PartialEq, Reflect)]
#[derive(Component, Clone, PartialEq, Default, Reflect)]
#[reflect(Component, PartialEq, Hash)]
pub struct VisibilityRange {
/// The range of distances, in world units, between which this entity will
@ -131,6 +132,20 @@ pub struct VisibilityRange {
///
/// `end_margin.start` must be greater than or equal to `start_margin.end`.
pub end_margin: Range<f32>,
/// If set to true, Bevy will use the center of the axis-aligned bounding
/// box ([`Aabb`]) as the position of the mesh for the purposes of
/// visibility range computation.
///
/// Otherwise, if this field is set to false, Bevy will use the origin of
/// the mesh as the mesh's position.
///
/// Usually you will want to leave this set to false, because different LODs
/// may have different AABBs, and smooth crossfades between LOD levels
/// require that all LODs of a mesh be at *precisely* the same position. If
/// you aren't using crossfading, however, and your meshes aren't centered
/// around their origins, then this flag may be useful.
pub use_aabb: bool,
}
impl Eq for VisibilityRange {}
@ -160,6 +175,7 @@ impl VisibilityRange {
Self {
start_margin: start..start,
end_margin: end..end,
use_aabb: false,
}
}
@ -390,14 +406,17 @@ pub fn check_visibility_ranges(
for (entity, entity_transform, maybe_model_aabb, visibility_range) in entity_query.iter_mut() {
let mut visibility = 0;
for (view_index, &(_, view_position)) in views.iter().enumerate() {
let model_pos = if let Some(model_aabb) = maybe_model_aabb {
let world_from_local = entity_transform.affine();
world_from_local.transform_point3a(model_aabb.center)
} else {
entity_transform.translation_vec3a()
// If instructed to use the AABB and the model has one, use its
// center as the model position. Otherwise, use the model's
// translation.
let model_position = match (visibility_range.use_aabb, maybe_model_aabb) {
(true, Some(model_aabb)) => entity_transform
.affine()
.transform_point3a(model_aabb.center),
_ => entity_transform.translation_vec3a(),
};
if visibility_range.is_visible_at_all((view_position - model_pos).length()) {
if visibility_range.is_visible_at_all((view_position - model_position).length()) {
visibility |= 1 << view_index;
}
}
@ -416,8 +435,9 @@ pub fn extract_visibility_ranges(
mut render_visibility_ranges: ResMut<RenderVisibilityRanges>,
visibility_ranges_query: Extract<Query<(Entity, &VisibilityRange)>>,
changed_ranges_query: Extract<Query<Entity, Changed<VisibilityRange>>>,
mut removed_visibility_ranges: Extract<RemovedComponents<VisibilityRange>>,
) {
if changed_ranges_query.is_empty() {
if changed_ranges_query.is_empty() && removed_visibility_ranges.read().next().is_none() {
return;
}

View file

@ -9,7 +9,6 @@ license = "MIT OR Apache-2.0"
keywords = ["bevy"]
[features]
default = ["bevy_sprite_picking_backend"]
bevy_sprite_picking_backend = ["bevy_picking", "bevy_window"]
serialize = ["dep:serde"]
webgl = []

View file

@ -63,8 +63,20 @@ use bevy_render::{
};
/// Adds support for 2D sprite rendering.
#[derive(Default)]
pub struct SpritePlugin;
pub struct SpritePlugin {
/// Whether to add the sprite picking backend to the app.
#[cfg(feature = "bevy_sprite_picking_backend")]
pub add_picking: bool,
}
impl Default for SpritePlugin {
fn default() -> Self {
Self {
#[cfg(feature = "bevy_sprite_picking_backend")]
add_picking: true,
}
}
}
pub const SPRITE_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(2763343953151597127);
pub const SPRITE_VIEW_BINDINGS_SHADER_HANDLE: Handle<Shader> =
@ -135,7 +147,9 @@ impl Plugin for SpritePlugin {
);
#[cfg(feature = "bevy_sprite_picking_backend")]
app.add_plugins(picking_backend::SpritePickingPlugin);
if self.add_picking {
app.add_plugins(picking_backend::SpritePickingPlugin);
}
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app

View file

@ -46,7 +46,6 @@ smallvec = "1.11"
accesskit = "0.17"
[features]
default = ["bevy_ui_picking_backend"]
serialize = ["serde", "smallvec/serde", "bevy_math/serialize"]
bevy_ui_picking_backend = ["bevy_picking"]

View file

@ -85,12 +85,17 @@ pub struct UiPlugin {
/// If set to false, the UI's rendering systems won't be added to the `RenderApp` and no UI elements will be drawn.
/// The layout and interaction components will still be updated as normal.
pub enable_rendering: bool,
/// Whether to add the UI picking backend to the app.
#[cfg(feature = "bevy_ui_picking_backend")]
pub add_picking: bool,
}
impl Default for UiPlugin {
fn default() -> Self {
Self {
enable_rendering: true,
#[cfg(feature = "bevy_ui_picking_backend")]
add_picking: true,
}
}
}
@ -217,7 +222,9 @@ impl Plugin for UiPlugin {
build_text_interop(app);
#[cfg(feature = "bevy_ui_picking_backend")]
app.add_plugins(picking_backend::UiPickingPlugin);
if self.add_picking {
app.add_plugins(picking_backend::UiPickingPlugin);
}
if !self.enable_rendering {
return;

View file

@ -279,10 +279,15 @@ pub fn update_image_content_size_system(
continue;
}
if let Some(size) = match &image.texture_atlas {
Some(atlas) => atlas.texture_rect(&atlases).map(|t| t.size()),
None => textures.get(&image.image).map(Image::size),
} {
if let Some(size) =
image
.rect
.map(|rect| rect.size().as_uvec2())
.or_else(|| match &image.texture_atlas {
Some(atlas) => atlas.texture_rect(&atlases).map(|t| t.size()),
None => textures.get(&image.image).map(Image::size),
})
{
// Update only if size or scale factor has changed to avoid needless layout calculations
if size != image_size.size
|| combined_scale_factor != *previous_combined_scale_factor

View file

@ -25,6 +25,7 @@ allow = [
exceptions = [
{ name = "unicode-ident", allow = [
"Unicode-DFS-2016",
"Unicode-3.0",
] },
{ name = "symphonia", allow = [
"MPL-2.0",

View file

@ -25,7 +25,6 @@ The default feature set enables most of the expected features of a game engine,
|bevy_mesh_picking_backend|Provides an implementation for picking meshes|
|bevy_pbr|Adds PBR rendering|
|bevy_picking|Provides picking functionality|
|bevy_remote|Enable the Bevy Remote Protocol|
|bevy_render|Provides rendering functionality|
|bevy_scene|Provides scene functionality|
|bevy_sprite|Provides sprite functionality|
@ -33,7 +32,7 @@ The default feature set enables most of the expected features of a game engine,
|bevy_state|Enable built in global state machines|
|bevy_text|Provides text functionality|
|bevy_ui|A custom ECS-driven UI framework|
|bevy_ui_picking_backend|Provides an implementation for picking ui|
|bevy_ui_picking_backend|Provides an implementation for picking UI|
|bevy_window|Windowing layer|
|bevy_winit|winit window and input backend|
|custom_cursor|Enable winit custom cursor support|
@ -62,6 +61,7 @@ The default feature set enables most of the expected features of a game engine,
|bevy_ci_testing|Enable systems that allow for automated testing on CI|
|bevy_debug_stepping|Enable stepping-based debugging of Bevy systems|
|bevy_dev_tools|Provides a collection of developer tools|
|bevy_remote|Enable the Bevy Remote Protocol|
|bmp|BMP image format support|
|dds|DDS compressed texture support|
|debug_glam_assert|Enable assertions in debug builds to check the validity of parameters passed to glam|

View file

@ -26,10 +26,12 @@ const MIN_ZOOM_DISTANCE: f32 = 0.5;
static NORMAL_VISIBILITY_RANGE_HIGH_POLY: VisibilityRange = VisibilityRange {
start_margin: 0.0..0.0,
end_margin: 3.0..4.0,
use_aabb: false,
};
static NORMAL_VISIBILITY_RANGE_LOW_POLY: VisibilityRange = VisibilityRange {
start_margin: 3.0..4.0,
end_margin: 8.0..9.0,
use_aabb: false,
};
// A visibility model that we use to always show a model (until the camera is so
@ -37,12 +39,14 @@ static NORMAL_VISIBILITY_RANGE_LOW_POLY: VisibilityRange = VisibilityRange {
static SINGLE_MODEL_VISIBILITY_RANGE: VisibilityRange = VisibilityRange {
start_margin: 0.0..0.0,
end_margin: 8.0..9.0,
use_aabb: false,
};
// A visibility range that we use to completely hide a model.
static INVISIBLE_VISIBILITY_RANGE: VisibilityRange = VisibilityRange {
start_margin: 0.0..0.0,
end_margin: 0.0..0.0,
use_aabb: false,
};
// Allows us to identify the main model.