red dot revolution

This commit is contained in:
2025-05-29 13:01:58 +02:00
parent 9b8715bf4a
commit 18a1a24520
4 changed files with 178 additions and 73 deletions

View File

@@ -1,96 +1,76 @@
use iced::mouse;
mod polygon_draw;
use iced::Subscription;
use iced::widget::canvas;
use iced::widget::canvas::Stroke;
use iced::widget::canvas::Style;
use iced::widget::{button, column, row, text};
use iced::{Color, Rectangle, Renderer, Theme};
use iced::widget::{Checkbox, button, checkbox, column, row, text};
use iced::{
Task,
time::{self, Duration},
};
use polygon_draw::PolygonFrame;
use std::f32::consts::PI;
use std::time::Instant;
use tokio::time::sleep;
fn main() -> iced::Result {
iced::run("My App", MyApp::update, MyApp::view)
iced::application("My App", MyApp::update, MyApp::view)
.subscription(MyApp::subscription)
.run_with(MyApp::new)
}
#[derive(Debug, Clone)]
enum Message {
ButtonPressedIncrement,
ButtonPressedDecrement,
Tick,
}
#[derive(Default)]
struct MyApp {
counter: f32,
polys: PolygonFrame,
time_last_frame: Instant,
revo_per_sec: f32,
}
impl MyApp {
fn new() -> (Self, Task<Message>) {
(
Self {
revo_per_sec: 1.0 / 2.0,
time_last_frame: Instant::now(),
polys: PolygonFrame {
radius: 128.0,
teta: 0.0,
},
},
Task::none(),
)
}
fn update(&mut self, message: Message) {
match message {
Message::ButtonPressedIncrement => self.counter += 32.0,
Message::ButtonPressedDecrement => {
if self.counter > 0.0 {
self.counter -= 32.0
}
Message::ButtonPressedIncrement => self.revo_per_sec *= 2.0,
Message::ButtonPressedDecrement => self.revo_per_sec /= 2.0,
Message::Tick => {
let time_btw = Instant::now().duration_since(self.time_last_frame);
self.polys.teta +=
2.0 * PI * self.revo_per_sec * (time_btw.as_millis() as f32 / 1_000.0);
self.polys.teta %= 2.0 * PI;
println!("Teta : {}", self.polys.teta);
self.time_last_frame = Instant::now();
}
}
}
fn view(&self) -> iced::Element<Message> {
column![
text(self.counter),
text(self.polys.radius),
row![
button("Increment").on_press(Message::ButtonPressedIncrement),
button("Decrement").on_press(Message::ButtonPressedDecrement),
],
canvas(Circle {
radius: self.counter
})
.height(500)
.width(500),
canvas(&self.polys).height(500).width(500),
]
.into()
}
}
struct Circle {
radius: f32,
}
impl<Message> canvas::Program<Message> for Circle {
// No internal state
type State = ();
fn draw(
&self,
_state: &(),
renderer: &Renderer,
_theme: &Theme,
bounds: Rectangle,
_cursor: mouse::Cursor,
) -> Vec<canvas::Geometry> {
// We prepare a new `Frame`
//println!("w:{}, h:{}", bounds.size().width, bounds.size().height);
let mut frame = canvas::Frame::new(renderer, bounds.size());
// We create a `Path` representing a simple circle
let circle = canvas::Path::circle(frame.center(), self.radius);
let line = canvas::Path::line(frame.center(), iced::Point { x: 0.0, y: 0.0 });
frame.stroke(
&line,
Stroke {
width: 5.0,
..Stroke::default()
},
);
// And fill it with some color
frame.stroke(
&circle,
Stroke {
width: 5.0,
style: Style::Solid(Color::from_rgba(0.0, 0.0, 0.0, 1.0)),
..Stroke::default()
},
);
// Then, we produce the geometry
vec![frame.into_geometry()]
fn subscription(&self) -> iced::Subscription<Message> {
time::every(Duration::from_millis(1)).map(|_| Message::Tick)
}
}

75
src/polygon_draw.rs Normal file
View File

@@ -0,0 +1,75 @@
use std::f32::consts::PI;
use iced::Vector;
use iced::mouse;
use iced::widget::canvas;
use iced::widget::canvas::Stroke;
use iced::widget::canvas::Style;
use iced::{Color, Rectangle, Renderer, Theme};
use std::time::SystemTime;
pub trait RotationExt {
fn rotate(&mut self, teta: f32) -> Self;
}
impl RotationExt for Vector {
fn rotate(&mut self, teta: f32) -> Self {
let temp_x = self.x;
let temp_y = self.y;
self.x = temp_x * teta.cos() - temp_y * teta.sin();
self.y = temp_x * teta.sin() + temp_y * teta.cos();
*self
}
}
pub struct PolygonFrame {
pub radius: f32,
pub teta: f32,
}
impl<Message> canvas::Program<Message> for PolygonFrame {
// No internal state
type State = ();
fn draw(
&self,
_state: &(),
renderer: &Renderer,
_theme: &Theme,
bounds: Rectangle,
_cursor: mouse::Cursor,
) -> Vec<canvas::Geometry> {
// We prepare a new `Frame`
let mut frame = canvas::Frame::new(renderer, bounds.size());
// We create a `Path` representing a simple circle
let circle = canvas::Path::circle(frame.center(), self.radius);
let mut vec = Vector::new(0.0, -self.radius);
let line = canvas::Path::line(
frame.center() + vec,
frame.center() + vec.rotate(2.0 * PI / 3.0),
);
let dot = canvas::Path::circle(frame.center() + vec.rotate(self.teta), 10.0);
frame.stroke(
&line,
Stroke {
width: 5.0,
..Stroke::default()
},
);
// And fill it with some color
frame.stroke(
&circle,
Stroke {
width: 5.0,
style: Style::Solid(Color::from_rgba(0.0, 0.0, 0.0, 1.0)),
..Stroke::default()
},
);
frame.fill(&dot, Color::from_rgb(1.0, 0.0, 0.0));
// Then, we produce the geometry
vec![frame.into_geometry()]
}
}