add covers_opaque

This commit is contained in:
griffi-gh 2024-03-24 21:35:44 +01:00
parent e488ef70b5
commit 5af38d7a2a
5 changed files with 96 additions and 28 deletions

View file

@ -122,7 +122,6 @@ impl UiElement for Slider {
// } else { // } else {
// vec2(15., ctx.measure.size.y) // vec2(15., ctx.measure.size.y)
// }; // };
let handle_size = vec2(self.handle_width, ctx.measure.size.y); let handle_size = vec2(self.handle_width, ctx.measure.size.y);
//Draw the track //Draw the track
@ -130,37 +129,25 @@ impl UiElement for Slider {
//However, if the handle is not opaque, we need to draw the background as the active part won't quite reach the end //However, if the handle is not opaque, we need to draw the background as the active part won't quite reach the end
//Of corse, if it's fully transparent, we don't need to draw it either //Of corse, if it's fully transparent, we don't need to draw it either
// if !(self.track_color.is_transparent() || (self.track_active_color.is_opaque() && self.handle_color.is_opaque() && self.value >= 1.)) { // if !(self.track_color.is_transparent() || (self.track_active_color.is_opaque() && self.handle_color.is_opaque() && self.value >= 1.)) {
// ctx.draw.add(UiDrawCommand::Rectangle { if !(self.track_active.covers_opaque() && self.handle.covers_opaque() && self.value >= 1.) {
// position: ctx.layout.position + ctx.measure.size * vec2(0., 0.5 - self.track_height_ratio / 2.),
// size: ctx.measure.size * vec2(1., self.track_height_ratio),
// color: self.track_color.into(),
// texture: None,
// rounded_corners: None,
// });
// }
self.track.draw( self.track.draw(
ctx.draw, ctx.draw,
ctx.layout.position + ctx.measure.size * vec2(0., 0.5 - self.track_height_ratio / 2.), ctx.layout.position + ctx.measure.size * vec2(0., 0.5 - self.track_height_ratio / 2.),
ctx.measure.size * vec2(1., self.track_height_ratio), ctx.measure.size * vec2(1., self.track_height_ratio),
); );
}
//"Active" part of the track //"Active" part of the track
//We can skip drawing it if it's fully transparent or value <= 0. //We can skip drawing it if it's fully transparent or value <= 0.
//But if the handle is not opaque, it should be visible even if value is zero //But if the handle is not opaque, it should be visible even if value is zero
// if !(self.track_active_color.is_transparent() || (self.value <= 0. && self.handle_color.is_opaque())) { // if !(self.track_active_color.is_transparent() || (self.value <= 0. && self.handle_color.is_opaque())) {
// ctx.draw.add(UiDrawCommand::Rectangle { if !(self.handle.covers_opaque() && self.value <= 0.) {
// position: ctx.layout.position + ctx.measure.size * vec2(0., 0.5 - self.track_height_ratio / 2.),
// size: (ctx.measure.size - handle_size * Vec2::X) * vec2(self.value, self.track_height_ratio) + handle_size * Vec2::X / 2.,
// color: self.track_active_color.into(),
// texture: None,
// rounded_corners: None,
// });
// }
self.track_active.draw( self.track_active.draw(
ctx.draw, ctx.draw,
ctx.layout.position + ctx.measure.size * vec2(0., 0.5 - self.track_height_ratio / 2.), ctx.layout.position + ctx.measure.size * vec2(0., 0.5 - self.track_height_ratio / 2.),
(ctx.measure.size - handle_size * Vec2::X) * vec2(self.value, self.track_height_ratio) + handle_size * Vec2::X / 2., (ctx.measure.size - handle_size * Vec2::X) * vec2(self.value, self.track_height_ratio) + handle_size * Vec2::X / 2.,
); );
}
// The handle // The handle
// if handle_size.x != 0. && !self.handle_color.is_transparent() { // if handle_size.x != 0. && !self.handle_color.is_transparent() {
@ -182,7 +169,9 @@ impl UiElement for Slider {
//handle events //handle events
if let Some(res) = ctx.input.check_active(ctx.measure.rect(ctx.layout.position)) { if let Some(res) = ctx.input.check_active(ctx.measure.rect(ctx.layout.position)) {
let new_value = match self.follow_mode { let new_value = match self.follow_mode {
SliderFollowMode::Absolute => ((res.position_in_rect.x - handle_size.x / 2.) / (ctx.measure.size.x - handle_size.x)).clamp(0., 1.), SliderFollowMode::Absolute => {
((res.position_in_rect.x - handle_size.x / 2.) / (ctx.measure.size.x - handle_size.x)).clamp(0., 1.)
},
SliderFollowMode::Relative => { SliderFollowMode::Relative => {
let delta = res.position_in_rect.x - res.last_position_in_rect.x; let delta = res.position_in_rect.x - res.last_position_in_rect.x;
let delta_ratio = delta / (ctx.measure.size.x - handle_size.x); let delta_ratio = delta / (ctx.measure.size.x - handle_size.x);

View file

@ -9,5 +9,16 @@ mod impls;
pub use rect::FrameRect; pub use rect::FrameRect;
pub trait Frame { pub trait Frame {
/// Draw the frame at the given position and size
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2); fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2);
/// Check if the frame is guaranteed to be fully opaque and fully cover the parent frame regardless of it's size
///
/// Returns true if the frame:
/// - Is fully opaque (i.e. `alpha >= 1.0`)
/// - Completely covers (or exceeds the size of) the frame
///
/// False negatives are acceptable, but false positives ***are not***.\
/// May be used for optimization purposes
fn covers_opaque(&self) -> bool { false }
} }

View file

@ -16,6 +16,9 @@ impl Frame for ImageHandle {
rounded_corners: None, rounded_corners: None,
}) })
} }
fn covers_opaque(&self) -> bool {
true
}
} }
impl Frame for FillColor { impl Frame for FillColor {
@ -28,6 +31,9 @@ impl Frame for FillColor {
rounded_corners: None, rounded_corners: None,
}) })
} }
fn covers_opaque(&self) -> bool {
self.is_opaque()
}
} }
// impl for various types resembling colors // impl for various types resembling colors
@ -38,24 +44,36 @@ impl Frame for Corners<Vec4> {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for (Vec4, Vec4, Vec4, Vec4) { impl Frame for (Vec4, Vec4, Vec4, Vec4) {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for ((f32, f32, f32, f32), (f32, f32, f32, f32), (f32, f32, f32, f32), (f32, f32, f32, f32)) { impl Frame for ((f32, f32, f32, f32), (f32, f32, f32, f32), (f32, f32, f32, f32), (f32, f32, f32, f32)) {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for [[f32; 4]; 4] { impl Frame for [[f32; 4]; 4] {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
// Corners (RGB): // Corners (RGB):
@ -64,24 +82,36 @@ impl Frame for Corners<Vec3> {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for (Vec3, Vec3, Vec3, Vec3) { impl Frame for (Vec3, Vec3, Vec3, Vec3) {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for ((f32, f32, f32), (f32, f32, f32), (f32, f32, f32), (f32, f32, f32)) { impl Frame for ((f32, f32, f32), (f32, f32, f32), (f32, f32, f32), (f32, f32, f32)) {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for [[f32; 3]; 4] { impl Frame for [[f32; 3]; 4] {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
// RGBA: // RGBA:
@ -90,18 +120,27 @@ impl Frame for Vec4 {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for (f32, f32, f32, f32) { impl Frame for (f32, f32, f32, f32) {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for [f32; 4] { impl Frame for [f32; 4] {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
// RGB: // RGB:
@ -110,16 +149,25 @@ impl Frame for Vec3 {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for (f32, f32, f32) { impl Frame for (f32, f32, f32) {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }
impl Frame for [f32; 3] { impl Frame for [f32; 3] {
fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) { fn draw(&self, draw: &mut UiDrawCommandList, position: Vec2, parent_size: Vec2) {
FillColor::from(*self).draw(draw, position, parent_size) FillColor::from(*self).draw(draw, position, parent_size)
} }
fn covers_opaque(&self) -> bool {
FillColor::from(*self).is_opaque()
}
} }

View file

@ -6,6 +6,9 @@ use crate::{
}; };
use super::{Frame, point::FramePoint2d}; use super::{Frame, point::FramePoint2d};
/// A rectangular frame
///
/// Can optionally be tinted, textured, and have rounded corners
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct FrameRect { pub struct FrameRect {
/// Background color of the frame\ /// Background color of the frame\
@ -126,4 +129,16 @@ impl Frame for FrameRect {
), ),
}); });
} }
fn covers_opaque(&self) -> bool {
self.top_left.x.absolute <= 0. &&
self.top_left.x.relative <= 0. &&
self.top_left.y.absolute <= 0. &&
self.top_left.y.relative <= 0. &&
self.bottom_right.x.absolute >= 0. &&
self.bottom_right.x.relative >= 1. &&
self.bottom_right.y.absolute >= 0. &&
self.bottom_right.y.relative >= 1. &&
self.color.is_opaque()
}
} }

View file

@ -9,6 +9,11 @@ impl Frame for FrameStack {
self.0.draw(draw, position, parent_size); self.0.draw(draw, position, parent_size);
self.1.draw(draw, position, parent_size); self.1.draw(draw, position, parent_size);
} }
fn covers_opaque(&self) -> bool {
self.0.covers_opaque() ||
self.1.covers_opaque()
}
} }
pub trait FrameStackExt: Frame { pub trait FrameStackExt: Frame {