diff options
author | 2024-05-03 07:23:55 +0200 | |
---|---|---|
committer | 2024-05-03 07:23:55 +0200 | |
commit | 4010e3983d40e24a5d7b590d8fec9801651199ce (patch) | |
tree | e0deb67cf993a2b67417d7e764c0685f03b50ddf | |
parent | eac5bcb64f17dfbb52b64ea4f95693462986bb69 (diff) | |
download | iced-4010e3983d40e24a5d7b590d8fec9801651199ce.tar.gz iced-4010e3983d40e24a5d7b590d8fec9801651199ce.tar.bz2 iced-4010e3983d40e24a5d7b590d8fec9801651199ce.zip |
Add `spin` mode to `ferris` example :crab:
-rw-r--r-- | core/src/angle.rs | 26 | ||||
-rw-r--r-- | core/src/rotation.rs | 7 | ||||
-rw-r--r-- | examples/ferris/Cargo.toml | 2 | ||||
-rw-r--r-- | examples/ferris/src/main.rs | 68 |
4 files changed, 87 insertions, 16 deletions
diff --git a/core/src/angle.rs b/core/src/angle.rs index 8322273c..9c8a9b24 100644 --- a/core/src/angle.rs +++ b/core/src/angle.rs @@ -1,7 +1,7 @@ use crate::{Point, Rectangle, Vector}; use std::f32::consts::{FRAC_PI_2, PI}; -use std::ops::{Add, AddAssign, Div, Mul, RangeInclusive, Sub, SubAssign}; +use std::ops::{Add, AddAssign, Div, Mul, RangeInclusive, Rem, Sub, SubAssign}; /// Degrees #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] @@ -48,6 +48,14 @@ impl From<Degrees> for f64 { } } +impl Mul<f32> for Degrees { + type Output = Degrees; + + fn mul(self, rhs: f32) -> Self::Output { + Self(self.0 * rhs) + } +} + impl num_traits::FromPrimitive for Degrees { fn from_i64(n: i64) -> Option<Self> { Some(Self(n as f32)) @@ -156,6 +164,14 @@ impl Add for Radians { } } +impl Add<Degrees> for Radians { + type Output = Self; + + fn add(self, rhs: Degrees) -> Self::Output { + Self(self.0 + rhs.0.to_radians()) + } +} + impl AddAssign for Radians { fn add_assign(&mut self, rhs: Radians) { self.0 = self.0 + rhs.0; @@ -202,6 +218,14 @@ impl Div for Radians { } } +impl Rem for Radians { + type Output = Self; + + fn rem(self, rhs: Self) -> Self::Output { + Self(self.0 % rhs.0) + } +} + impl PartialEq<f32> for Radians { fn eq(&self, other: &f32) -> bool { self.0.eq(other) diff --git a/core/src/rotation.rs b/core/src/rotation.rs index 00a8c302..afa8d79e 100644 --- a/core/src/rotation.rs +++ b/core/src/rotation.rs @@ -31,6 +31,13 @@ impl Rotation { } } + /// Returns a mutable reference to the angle of the [`Rotation`] in [`Radians`]. + pub fn radians_mut(&mut self) -> &mut Radians { + match self { + Rotation::Floating(radians) | Rotation::Solid(radians) => radians, + } + } + /// Returns the angle of the [`Rotation`] in [`Degrees`]. pub fn degrees(self) -> Degrees { Degrees(self.radians().0.to_degrees()) diff --git a/examples/ferris/Cargo.toml b/examples/ferris/Cargo.toml index 0d91749b..e98341d2 100644 --- a/examples/ferris/Cargo.toml +++ b/examples/ferris/Cargo.toml @@ -7,4 +7,4 @@ publish = false [dependencies] iced.workspace = true -iced.features = ["image", "debug"] +iced.features = ["image", "tokio", "debug"] diff --git a/examples/ferris/src/main.rs b/examples/ferris/src/main.rs index d846f560..b7536740 100644 --- a/examples/ferris/src/main.rs +++ b/examples/ferris/src/main.rs @@ -1,10 +1,16 @@ -use iced::widget::{column, container, image, pick_list, row, slider, text}; +use iced::time::Instant; +use iced::widget::{ + checkbox, column, container, image, pick_list, row, slider, text, +}; +use iced::window; use iced::{ - Alignment, Color, ContentFit, Degrees, Element, Length, Rotation, Theme, + Alignment, Color, ContentFit, Degrees, Element, Length, Radians, Rotation, + Subscription, Theme, }; pub fn main() -> iced::Result { iced::program("Ferris - Iced", Image::update, Image::view) + .subscription(Image::subscription) .theme(|_| Theme::TokyoNight) .run() } @@ -13,6 +19,8 @@ struct Image { width: f32, rotation: Rotation, content_fit: ContentFit, + spin: bool, + last_tick: Instant, } #[derive(Debug, Clone, Copy)] @@ -21,6 +29,8 @@ enum Message { RotationStrategyChanged(RotationStrategy), RotationChanged(Degrees), ContentFitChanged(ContentFit), + SpinToggled(bool), + RedrawRequested(Instant), } impl Image { @@ -50,6 +60,29 @@ impl Image { Message::ContentFitChanged(content_fit) => { self.content_fit = content_fit; } + Message::SpinToggled(spin) => { + self.spin = spin; + self.last_tick = Instant::now(); + } + Message::RedrawRequested(now) => { + const ROTATION_SPEED: Degrees = Degrees(360.0); + + let delta = (now - self.last_tick).as_millis() as f32 / 1_000.0; + + *self.rotation.radians_mut() = (self.rotation.radians() + + ROTATION_SPEED * delta) + % (2.0 * Radians::PI); + + self.last_tick = now; + } + } + } + + fn subscription(&self) -> Subscription<Message> { + if self.spin { + window::frames().map(Message::RedrawRequested) + } else { + Subscription::none() } } @@ -111,18 +144,23 @@ impl Image { Message::RotationStrategyChanged, ) .width(Length::Fill), - column![ - slider( - Degrees::RANGE, - self.rotation.degrees(), - Message::RotationChanged - ), - text(format!( - "Rotation: {:.0}°", - f32::from(self.rotation.degrees()) - )) - .size(14) - .line_height(1.0) + row![ + column![ + slider( + Degrees::RANGE, + self.rotation.degrees(), + Message::RotationChanged + ), + text(format!( + "Rotation: {:.0}°", + f32::from(self.rotation.degrees()) + )) + .size(14) + .line_height(1.0) + ] + .spacing(5) + .align_items(Alignment::Center), + checkbox("Spin!", self.spin).on_toggle(Message::SpinToggled) ] .spacing(5) .align_items(Alignment::Center) @@ -141,6 +179,8 @@ impl Default for Image { width: 300.0, rotation: Rotation::default(), content_fit: ContentFit::default(), + spin: false, + last_tick: Instant::now(), } } } |