diff --git a/crates/bevy_sprite/src/render/sprite_sheet.frag b/crates/bevy_sprite/src/render/sprite_sheet.frag index 8c8d9217f08d1..f7a430946cb37 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.frag +++ b/crates/bevy_sprite/src/render/sprite_sheet.frag @@ -2,6 +2,7 @@ layout(location = 0) in vec2 v_Uv; layout(location = 1) in vec4 v_Color; +layout(location = 2) in vec4 v_Bounds; layout(location = 0) out vec4 o_Target; @@ -9,6 +10,10 @@ layout(set = 1, binding = 2) uniform texture2D TextureAtlas_texture; layout(set = 1, binding = 3) uniform sampler TextureAtlas_texture_sampler; void main() { + if(gl_FragCoord.x >= v_Bounds.x || gl_FragCoord.x <= v_Bounds.z || + gl_FragCoord.y >= v_Bounds.y || gl_FragCoord.y <= v_Bounds.w) { + discard; + } o_Target = v_Color * texture( sampler2D(TextureAtlas_texture, TextureAtlas_texture_sampler), v_Uv); diff --git a/crates/bevy_sprite/src/render/sprite_sheet.vert b/crates/bevy_sprite/src/render/sprite_sheet.vert index 62ecf3323785a..1bc5a8514c06f 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -6,6 +6,7 @@ layout(location = 2) in vec2 Vertex_Uv; layout(location = 0) out vec2 v_Uv; layout(location = 1) out vec4 v_Color; +layout(location = 2) out vec4 v_Bounds; layout(set = 0, binding = 0) uniform CameraViewProj { mat4 ViewProj; @@ -34,6 +35,7 @@ layout(set = 2, binding = 1) uniform TextureAtlasSprite { vec4 color; uint index; uint flip; + vec4 bounds; }; void main() { @@ -82,4 +84,5 @@ void main() { v_Color = color; gl_Position = ViewProj * SpriteTransform * vec4(vertex_position, 1.0); + v_Bounds = bounds; } diff --git a/crates/bevy_sprite/src/texture_atlas.rs b/crates/bevy_sprite/src/texture_atlas.rs index 76df36000f6bb..d0632d0618e02 100644 --- a/crates/bevy_sprite/src/texture_atlas.rs +++ b/crates/bevy_sprite/src/texture_atlas.rs @@ -1,7 +1,7 @@ use crate::Rect; use bevy_asset::Handle; use bevy_core::Bytes; -use bevy_math::Vec2; +use bevy_math::{Vec2, Vec4}; use bevy_reflect::TypeUuid; use bevy_render::{ color::Color, @@ -33,6 +33,7 @@ pub struct TextureAtlasSprite { pub index: u32, pub flip_x: bool, pub flip_y: bool, + pub bounds: Vec4, } impl RenderResource for TextureAtlasSprite { @@ -50,7 +51,8 @@ impl RenderResource for TextureAtlasSprite { self.color.write_bytes(color_buf); // Write the index buffer - let (index_buf, flip_buf) = rest.split_at_mut(4); + let (index_buf, rest) = rest.split_at_mut(4); + let (flip_buf, bounds_buf) = rest.split_at_mut(4); self.index.write_bytes(index_buf); // First bit means flip x, second bit means flip y @@ -58,6 +60,8 @@ impl RenderResource for TextureAtlasSprite { flip_buf[1] = 0; flip_buf[2] = 0; flip_buf[3] = 0; + + self.bounds.write_bytes(bounds_buf); } fn texture(&self) -> Option<&Handle> { @@ -72,6 +76,7 @@ impl Default for TextureAtlasSprite { color: Color::WHITE, flip_x: false, flip_y: false, + bounds: Default::default(), } } } diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 9e26a456b5207..749d738f6d6a1 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -1,4 +1,4 @@ -use bevy_math::{Mat4, Vec3}; +use bevy_math::{Mat4, Vec3, Vec4}; use bevy_render::{ draw::{Draw, DrawContext, DrawError, Drawable}, mesh, @@ -21,6 +21,7 @@ pub struct DrawableText<'a> { pub text_glyphs: &'a Vec, pub msaa: &'a Msaa, pub font_quad_vertex_layout: &'a VertexBufferLayout, + pub bounds: Vec4, } impl<'a> Drawable for DrawableText<'a> { @@ -74,6 +75,7 @@ impl<'a> Drawable for DrawableText<'a> { color: self.sections[tv.section_index].style.color, flip_x: false, flip_y: false, + bounds: self.bounds, }; // To get the rendering right for non-one scaling factors, we need diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index 112ce1cac0c11..1d51138826514 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -112,6 +112,7 @@ pub fn draw_text2d_system( font_quad_vertex_layout: &font_quad_vertex_layout, scale_factor, sections: &text.sections, + bounds: Default::default(), }; drawable_text.draw(&mut draw, &mut context).unwrap(); diff --git a/crates/bevy_ui/src/flex/mod.rs b/crates/bevy_ui/src/flex/mod.rs index 2b89351211cc9..ec3788c69fb4c 100644 --- a/crates/bevy_ui/src/flex/mod.rs +++ b/crates/bevy_ui/src/flex/mod.rs @@ -1,15 +1,16 @@ mod convert; -use crate::{CalculatedSize, Node, Style}; +use crate::{CalculatedSize, Node, Overflow, Style}; use bevy_app::EventReader; +use bevy_ecs::system::QuerySet; use bevy_ecs::{ entity::Entity, query::{Changed, FilterFetch, With, Without, WorldQuery}, system::{Query, Res, ResMut}, }; use bevy_log::warn; -use bevy_math::Vec2; -use bevy_transform::prelude::{Children, Parent, Transform}; +use bevy_math::{Vec2, Vec3, Vec4}; +use bevy_transform::prelude::{Children, GlobalTransform, Parent, Transform}; use bevy_utils::HashMap; use bevy_window::{Window, WindowId, WindowScaleFactorChanged, Windows}; use std::fmt; @@ -187,6 +188,53 @@ pub enum FlexError { unsafe impl Send for FlexSurface {} unsafe impl Sync for FlexSurface {} +pub fn bounds_node_system( + windows: Res, + mut query_set: QuerySet<( + Query<(Option<&Parent>, &Style, &Node, &GlobalTransform)>, + Query<&mut Node>, + )>, + query: Query>, +) { + // y gets flipped somewhere.. + let window = windows.get_primary().unwrap(); + let window_height = window.height(); + let get_bounds = |position: Vec3, size: Vec2| -> Vec4 { + Vec4::new( + position.x - size.x / 2.0, + window_height - (position.y + size.y / 2.0), + position.x + size.x / 2.0, + window_height - (position.y - size.y / 2.0), + ) + }; + for entity in query.iter() { + let mut current_entity = entity; + let mut bounds = Default::default(); + loop { + if let Ok((parent, style, node, global_transform)) = query_set.q0().get(current_entity) + { + if current_entity == entity { + bounds = get_bounds(global_transform.translation, node.size); + } + if style.overflow == Overflow::Hidden { + bounds = get_bounds(global_transform.translation, node.size); + break; + } + if let Some(parent) = parent { + current_entity = parent.0; + } else { + break; + } + } else { + break; + } + } + if let Ok(mut node) = query_set.q1_mut().get_mut(entity) { + node.bounds = bounds; + } + } +} + #[allow(clippy::too_many_arguments)] pub fn flex_node_system( windows: Res, diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 352dba04f4972..8b7f40c2f9e52 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -58,6 +58,7 @@ impl Plugin for UiPlugin { .register_type::>() .register_type::