diff options
author | 2023-10-24 05:34:03 +0200 | |
---|---|---|
committer | 2024-02-02 02:24:45 +0100 | |
commit | f4d66486016076bb339a338bc589645119962d1e (patch) | |
tree | bbb9c4d996216893296cf4323857323542d6e757 /core | |
parent | a6e91d13d5d43796d0e6bb570fb4f010cf27921a (diff) | |
download | iced-f4d66486016076bb339a338bc589645119962d1e.tar.gz iced-f4d66486016076bb339a338bc589645119962d1e.tar.bz2 iced-f4d66486016076bb339a338bc589645119962d1e.zip |
Introduce `with_transformation` to `Renderer` trait
Diffstat (limited to 'core')
-rw-r--r-- | core/Cargo.toml | 1 | ||||
-rw-r--r-- | core/src/lib.rs | 2 | ||||
-rw-r--r-- | core/src/mouse/interaction.rs | 1 | ||||
-rw-r--r-- | core/src/renderer.rs | 20 | ||||
-rw-r--r-- | core/src/renderer/null.rs | 8 | ||||
-rw-r--r-- | core/src/transformation.rs | 119 |
6 files changed, 145 insertions, 6 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml index 32dd3df2..2360e822 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -12,6 +12,7 @@ keywords.workspace = true [dependencies] bitflags.workspace = true +glam.workspace = true log.workspace = true num-traits.workspace = true smol_str.workspace = true diff --git a/core/src/lib.rs b/core/src/lib.rs index bbc973f0..002336ee 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -49,6 +49,7 @@ mod rectangle; mod shadow; mod shell; mod size; +mod transformation; mod vector; pub use alignment::Alignment; @@ -75,6 +76,7 @@ pub use shadow::Shadow; pub use shell::Shell; pub use size::Size; pub use text::Text; +pub use transformation::Transformation; pub use vector::Vector; pub use widget::Widget; diff --git a/core/src/mouse/interaction.rs b/core/src/mouse/interaction.rs index 072033fd..6ad66229 100644 --- a/core/src/mouse/interaction.rs +++ b/core/src/mouse/interaction.rs @@ -13,4 +13,5 @@ pub enum Interaction { ResizingHorizontally, ResizingVertically, NotAllowed, + ZoomIn, } diff --git a/core/src/renderer.rs b/core/src/renderer.rs index 0af74bb3..1139b41c 100644 --- a/core/src/renderer.rs +++ b/core/src/renderer.rs @@ -5,7 +5,9 @@ mod null; #[cfg(debug_assertions)] pub use null::Null; -use crate::{Background, Border, Color, Rectangle, Shadow, Size, Vector}; +use crate::{ + Background, Border, Color, Rectangle, Shadow, Size, Transformation, Vector, +}; /// A component that can be used by widgets to draw themselves on a screen. pub trait Renderer: Sized { @@ -14,12 +16,24 @@ pub trait Renderer: Sized { /// The layer will clip its contents to the provided `bounds`. fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)); - /// Applies a `translation` to the primitives recorded in the given closure. + /// Applies a [`Transformation`] to the primitives recorded in the given closure. + fn with_transformation( + &mut self, + transformation: Transformation, + f: impl FnOnce(&mut Self), + ); + + /// Applies a translation to the primitives recorded in the given closure. fn with_translation( &mut self, translation: Vector, f: impl FnOnce(&mut Self), - ); + ) { + self.with_transformation( + Transformation::translate(translation.x, translation.y), + f, + ); + } /// Fills a [`Quad`] with the provided [`Background`]. fn fill_quad(&mut self, quad: Quad, background: impl Into<Background>); diff --git a/core/src/renderer/null.rs b/core/src/renderer/null.rs index 455daa42..75a3c8b6 100644 --- a/core/src/renderer/null.rs +++ b/core/src/renderer/null.rs @@ -1,7 +1,9 @@ use crate::alignment; use crate::renderer::{self, Renderer}; use crate::text::{self, Text}; -use crate::{Background, Color, Font, Pixels, Point, Rectangle, Size, Vector}; +use crate::{ + Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation, +}; use std::borrow::Cow; @@ -21,9 +23,9 @@ impl Null { impl Renderer for Null { fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {} - fn with_translation( + fn with_transformation( &mut self, - _translation: Vector, + _transformation: Transformation, _f: impl FnOnce(&mut Self), ) { } diff --git a/core/src/transformation.rs b/core/src/transformation.rs new file mode 100644 index 00000000..b2c488b0 --- /dev/null +++ b/core/src/transformation.rs @@ -0,0 +1,119 @@ +use crate::{Point, Rectangle, Size, Vector}; + +use glam::{Mat4, Vec3, Vec4}; +use std::ops::Mul; + +/// A 2D transformation matrix. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Transformation(Mat4); + +impl Transformation { + /// A [`Transformation`] that preserves whatever is transformed. + pub const IDENTITY: Self = Self(Mat4::IDENTITY); + + /// Creates an orthographic projection. + #[rustfmt::skip] + pub fn orthographic(width: u32, height: u32) -> Transformation { + Transformation(Mat4::orthographic_rh_gl( + 0.0, width as f32, + height as f32, 0.0, + -1.0, 1.0 + )) + } + + /// Creates a translate transformation. + pub fn translate(x: f32, y: f32) -> Transformation { + Transformation(Mat4::from_translation(Vec3::new(x, y, 0.0))) + } + + /// Creates a uniform scaling transformation. + pub fn scale(scaling: f32) -> Transformation { + Transformation(Mat4::from_scale(Vec3::new(scaling, scaling, 1.0))) + } + + /// Returns the scale factor of the [`Transformation`]. + pub fn scale_factor(&self) -> f32 { + self.0.x_axis.x + } + + /// Returns the translation of the [`Transformation`]. + pub fn translation(&self) -> Vector { + Vector::new(self.0.w_axis.x, self.0.w_axis.y) + } +} + +impl Mul for Transformation { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + Transformation(self.0 * rhs.0) + } +} + +impl Mul<Transformation> for Point { + type Output = Self; + + fn mul(self, transformation: Transformation) -> Self { + let point = transformation + .0 + .mul_vec4(Vec4::new(self.x, self.y, 1.0, 1.0)); + + Point::new(point.x, point.y) + } +} + +impl Mul<Transformation> for Vector { + type Output = Self; + + fn mul(self, transformation: Transformation) -> Self { + let new_vector = transformation + .0 + .mul_vec4(Vec4::new(self.x, self.y, 1.0, 0.0)); + + Vector::new(new_vector.x, new_vector.y) + } +} + +impl Mul<Transformation> for Size { + type Output = Self; + + fn mul(self, transformation: Transformation) -> Self { + let new_size = transformation.0.mul_vec4(Vec4::new( + self.width, + self.height, + 1.0, + 0.0, + )); + + Size::new(new_size.x, new_size.y) + } +} + +impl Mul<Transformation> for Rectangle { + type Output = Self; + + fn mul(self, transformation: Transformation) -> Self { + let position = self.position(); + let size = self.size(); + + Self::new(position * transformation, size * transformation) + } +} + +impl AsRef<[f32; 16]> for Transformation { + fn as_ref(&self) -> &[f32; 16] { + self.0.as_ref() + } +} + +impl From<Transformation> for [f32; 16] { + fn from(t: Transformation) -> [f32; 16] { + *t.as_ref() + } +} + +impl From<Transformation> for Mat4 { + fn from(transformation: Transformation) -> Self { + transformation.0 + } +} |