Add spin mode to ferris example 🦀
This commit is contained in:
parent
eac5bcb64f
commit
4010e3983d
4 changed files with 87 additions and 16 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{Point, Rectangle, Vector};
|
use crate::{Point, Rectangle, Vector};
|
||||||
|
|
||||||
use std::f32::consts::{FRAC_PI_2, PI};
|
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
|
/// Degrees
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
#[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 {
|
impl num_traits::FromPrimitive for Degrees {
|
||||||
fn from_i64(n: i64) -> Option<Self> {
|
fn from_i64(n: i64) -> Option<Self> {
|
||||||
Some(Self(n as f32))
|
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 {
|
impl AddAssign for Radians {
|
||||||
fn add_assign(&mut self, rhs: Radians) {
|
fn add_assign(&mut self, rhs: Radians) {
|
||||||
self.0 = self.0 + rhs.0;
|
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 {
|
impl PartialEq<f32> for Radians {
|
||||||
fn eq(&self, other: &f32) -> bool {
|
fn eq(&self, other: &f32) -> bool {
|
||||||
self.0.eq(other)
|
self.0.eq(other)
|
||||||
|
|
|
||||||
|
|
@ -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`].
|
/// Returns the angle of the [`Rotation`] in [`Degrees`].
|
||||||
pub fn degrees(self) -> Degrees {
|
pub fn degrees(self) -> Degrees {
|
||||||
Degrees(self.radians().0.to_degrees())
|
Degrees(self.radians().0.to_degrees())
|
||||||
|
|
|
||||||
|
|
@ -7,4 +7,4 @@ publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced.workspace = true
|
iced.workspace = true
|
||||||
iced.features = ["image", "debug"]
|
iced.features = ["image", "tokio", "debug"]
|
||||||
|
|
|
||||||
|
|
@ -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::{
|
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 {
|
pub fn main() -> iced::Result {
|
||||||
iced::program("Ferris - Iced", Image::update, Image::view)
|
iced::program("Ferris - Iced", Image::update, Image::view)
|
||||||
|
.subscription(Image::subscription)
|
||||||
.theme(|_| Theme::TokyoNight)
|
.theme(|_| Theme::TokyoNight)
|
||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
|
|
@ -13,6 +19,8 @@ struct Image {
|
||||||
width: f32,
|
width: f32,
|
||||||
rotation: Rotation,
|
rotation: Rotation,
|
||||||
content_fit: ContentFit,
|
content_fit: ContentFit,
|
||||||
|
spin: bool,
|
||||||
|
last_tick: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|
@ -21,6 +29,8 @@ enum Message {
|
||||||
RotationStrategyChanged(RotationStrategy),
|
RotationStrategyChanged(RotationStrategy),
|
||||||
RotationChanged(Degrees),
|
RotationChanged(Degrees),
|
||||||
ContentFitChanged(ContentFit),
|
ContentFitChanged(ContentFit),
|
||||||
|
SpinToggled(bool),
|
||||||
|
RedrawRequested(Instant),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
|
|
@ -50,6 +60,29 @@ impl Image {
|
||||||
Message::ContentFitChanged(content_fit) => {
|
Message::ContentFitChanged(content_fit) => {
|
||||||
self.content_fit = 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,
|
Message::RotationStrategyChanged,
|
||||||
)
|
)
|
||||||
.width(Length::Fill),
|
.width(Length::Fill),
|
||||||
column![
|
row![
|
||||||
slider(
|
column![
|
||||||
Degrees::RANGE,
|
slider(
|
||||||
self.rotation.degrees(),
|
Degrees::RANGE,
|
||||||
Message::RotationChanged
|
self.rotation.degrees(),
|
||||||
),
|
Message::RotationChanged
|
||||||
text(format!(
|
),
|
||||||
"Rotation: {:.0}°",
|
text(format!(
|
||||||
f32::from(self.rotation.degrees())
|
"Rotation: {:.0}°",
|
||||||
))
|
f32::from(self.rotation.degrees())
|
||||||
.size(14)
|
))
|
||||||
.line_height(1.0)
|
.size(14)
|
||||||
|
.line_height(1.0)
|
||||||
|
]
|
||||||
|
.spacing(5)
|
||||||
|
.align_items(Alignment::Center),
|
||||||
|
checkbox("Spin!", self.spin).on_toggle(Message::SpinToggled)
|
||||||
]
|
]
|
||||||
.spacing(5)
|
.spacing(5)
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
|
|
@ -141,6 +179,8 @@ impl Default for Image {
|
||||||
width: 300.0,
|
width: 300.0,
|
||||||
rotation: Rotation::default(),
|
rotation: Rotation::default(),
|
||||||
content_fit: ContentFit::default(),
|
content_fit: ContentFit::default(),
|
||||||
|
spin: false,
|
||||||
|
last_tick: Instant::now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue