Image opacity support

This commit is contained in:
Jonathan Johnson 2024-09-16 14:15:49 -07:00
parent 01b764de0b
commit e0df3b0017
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
4 changed files with 34 additions and 13 deletions

View file

@ -45,6 +45,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
resize event. resize event.
- `PlatformWindow::outer_size` is a new function that returns the window's - `PlatformWindow::outer_size` is a new function that returns the window's
current outer size. current outer size.
- `Graphics::draw_texture` and `Graphics::draw_textured_shape` now both accept
an opactiy parameter controlling how opaque the texture should be rendered at.
### Changed ### Changed
@ -161,6 +163,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
initialized. initialized.
- `Window::on_file_drop` is a new callback that is invoked when file drop events - `Window::on_file_drop` is a new callback that is invoked when file drop events
occur for the window. occur for the window.
- `Image::opacity` allows rendering the image with a given opacity.
[139]: https://github.com/khonsulabs/cushy/issues/139 [139]: https://github.com/khonsulabs/cushy/issues/139

14
Cargo.lock generated
View file

@ -117,9 +117,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.88" version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
[[package]] [[package]]
name = "appit" name = "appit"
@ -418,9 +418,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.1.18" version = "1.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800"
dependencies = [ dependencies = [
"jobserver", "jobserver",
"libc", "libc",
@ -1311,7 +1311,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]] [[package]]
name = "kludgine" name = "kludgine"
version = "0.11.0" version = "0.11.0"
source = "git+https://github.com/khonsulabs/kludgine#eccacdaffe4a60d1887a201a68656f0058a12088" source = "git+https://github.com/khonsulabs/kludgine#186a350402da7068aea248801477376611b5f12a"
dependencies = [ dependencies = [
"ahash", "ahash",
"alot", "alot",
@ -1963,9 +1963,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.20.0" version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "orbclient" name = "orbclient"

View file

@ -170,14 +170,18 @@ impl<'clip, 'gfx, 'pass> Graphics<'clip, 'gfx, 'pass> {
} }
/// Draws `texture` at `destination`, scaling as necessary. /// Draws `texture` at `destination`, scaling as necessary.
pub fn draw_texture<Unit>(&mut self, texture: &impl TextureSource, destination: Rect<Unit>) pub fn draw_texture<Unit>(
where &mut self,
texture: &impl TextureSource,
destination: Rect<Unit>,
opacity: ZeroToOne,
) where
Unit: figures::ScreenUnit + ShaderScalable, Unit: figures::ScreenUnit + ShaderScalable,
i32: From<<Unit as IntoSigned>::Signed>, i32: From<<Unit as IntoSigned>::Signed>,
{ {
let translate = Point::<Unit>::from_px(self.translation(), self.scale()); let translate = Point::<Unit>::from_px(self.translation(), self.scale());
self.renderer self.renderer
.draw_texture(texture, destination + translate, *self.opacity); .draw_texture(texture, destination + translate, *(self.opacity * opacity));
} }
/// Draws a shape that was created with texture coordinates, applying the /// Draws a shape that was created with texture coordinates, applying the
@ -186,16 +190,18 @@ impl<'clip, 'gfx, 'pass> Graphics<'clip, 'gfx, 'pass> {
&mut self, &mut self,
shape: impl Into<Drawable<&'shape Shape, Unit>>, shape: impl Into<Drawable<&'shape Shape, Unit>>,
texture: &impl TextureSource, texture: &impl TextureSource,
opacity: ZeroToOne,
) where ) where
Unit: Zero + ShaderScalable + figures::ScreenUnit + Copy, Unit: Zero + ShaderScalable + figures::ScreenUnit + Copy,
i32: From<<Unit as IntoSigned>::Signed>, i32: From<<Unit as IntoSigned>::Signed>,
Shape: ShapeSource<Unit, true> + 'shape, Shape: ShapeSource<Unit, true> + 'shape,
{ {
let mut shape = shape.into(); let mut shape = shape.into();
let effective_opacity = self.opacity * opacity;
shape.opacity = Some( shape.opacity = Some(
shape shape
.opacity .opacity
.map_or(*self.opacity, |opacity| opacity * *self.opacity), .map_or(*effective_opacity, |opacity| opacity * *effective_opacity),
); );
shape.translation += Point::<Unit>::from_px(self.translation(), self.scale()); shape.translation += Point::<Unit>::from_px(self.translation(), self.scale());
self.renderer.draw_textured_shape(shape, texture); self.renderer.draw_textured_shape(shape, texture);

View file

@ -5,7 +5,7 @@ use figures::{FloatConversion, IntoSigned, IntoUnsigned, Point, Rect, Size, Zero
use kludgine::{AnyTexture, CollectedTexture, LazyTexture, SharedTexture, Texture, TextureRegion}; use kludgine::{AnyTexture, CollectedTexture, LazyTexture, SharedTexture, Texture, TextureRegion};
use crate::animation::ZeroToOne; use crate::animation::ZeroToOne;
use crate::context::LayoutContext; use crate::context::{LayoutContext, Trackable};
use crate::value::{IntoValue, Source, Value}; use crate::value::{IntoValue, Source, Value};
use crate::widget::Widget; use crate::widget::Widget;
use crate::ConstraintLimit; use crate::ConstraintLimit;
@ -17,6 +17,8 @@ pub struct Image {
pub contents: Value<AnyTexture>, pub contents: Value<AnyTexture>,
/// The scaling strategy to apply. /// The scaling strategy to apply.
pub scaling: Value<ImageScaling>, pub scaling: Value<ImageScaling>,
/// The opacity to render the image with.
pub opacity: Value<ZeroToOne>,
} }
impl Image { impl Image {
@ -26,6 +28,7 @@ impl Image {
Self { Self {
contents: contents.into_value(), contents: contents.into_value(),
scaling: Value::default(), scaling: Value::default(),
opacity: Value::Constant(ZeroToOne::ONE),
} }
} }
@ -36,6 +39,13 @@ impl Image {
self self
} }
/// Applies `opacity` when drawing the image, returns self.
#[must_use]
pub fn opacity(mut self, opacity: impl IntoValue<ZeroToOne>) -> Self {
self.opacity = opacity.into_value();
self
}
/// Applies the aspect-fit scaling strategy and returns self. /// Applies the aspect-fit scaling strategy and returns self.
/// ///
/// The aspect-fit scaling strategy scales the image to be the largest size /// The aspect-fit scaling strategy scales the image to be the largest size
@ -145,9 +155,11 @@ impl Image {
impl Widget for Image { impl Widget for Image {
fn redraw(&mut self, context: &mut crate::context::GraphicsContext<'_, '_, '_, '_>) { fn redraw(&mut self, context: &mut crate::context::GraphicsContext<'_, '_, '_, '_>) {
self.contents.invalidate_when_changed(context);
let opacity = self.opacity.get_tracking_redraw(context);
self.contents.map(|texture| { self.contents.map(|texture| {
let rect = self.calculate_image_rect(texture, context.gfx.size(), context); let rect = self.calculate_image_rect(texture, context.gfx.size(), context);
context.gfx.draw_texture(texture, rect); context.gfx.draw_texture(texture, rect, opacity);
}); });
} }