summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-05-03 07:23:55 +0200
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-05-03 07:23:55 +0200
commit4010e3983d40e24a5d7b590d8fec9801651199ce (patch)
treee0deb67cf993a2b67417d7e764c0685f03b50ddf
parenteac5bcb64f17dfbb52b64ea4f95693462986bb69 (diff)
downloadiced-4010e3983d40e24a5d7b590d8fec9801651199ce.tar.gz
iced-4010e3983d40e24a5d7b590d8fec9801651199ce.tar.bz2
iced-4010e3983d40e24a5d7b590d8fec9801651199ce.zip
Add `spin` mode to `ferris` example :crab:
-rw-r--r--core/src/angle.rs26
-rw-r--r--core/src/rotation.rs7
-rw-r--r--examples/ferris/Cargo.toml2
-rw-r--r--examples/ferris/src/main.rs68
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(),
}
}
}