mirror of
https://github.com/bevyengine/bevy
synced 2024-11-23 13:13:49 +00:00
Merge branch 'main' into ignore_transparancy_on_sprite_picking
This commit is contained in:
commit
50e862d1ad
19 changed files with 141 additions and 46 deletions
20
Cargo.toml
20
Cargo.toml
|
@ -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"
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 })
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"]
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"]
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -25,6 +25,7 @@ allow = [
|
|||
exceptions = [
|
||||
{ name = "unicode-ident", allow = [
|
||||
"Unicode-DFS-2016",
|
||||
"Unicode-3.0",
|
||||
] },
|
||||
{ name = "symphonia", allow = [
|
||||
"MPL-2.0",
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue