From 116a07ba274a35247c8ef39a7c73ea60926ec3d4 Mon Sep 17 00:00:00 2001 From: Dukantic Date: Thu, 29 May 2025 13:01:58 +0200 Subject: [PATCH] red dot revolution --- Cargo.lock | 64 +++++++++++++++++++++++--- Cargo.toml | 4 +- src/main.rs | 108 ++++++++++++++++++-------------------------- src/polygon_draw.rs | 75 ++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+), 73 deletions(-) create mode 100644 src/polygon_draw.rs diff --git a/Cargo.lock b/Cargo.lock index c930f0a..111ad64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,15 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + [[package]] name = "adler2" version = "2.0.0" @@ -282,6 +291,21 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -1190,6 +1214,12 @@ dependencies = [ "wasi 0.14.2+wasi-0.2.4", ] +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + [[package]] name = "gl_generator" version = "0.14.0" @@ -1408,6 +1438,7 @@ dependencies = [ "iced_core", "log", "rustc-hash 2.1.1", + "tokio", "wasm-bindgen-futures", "wasm-timer", ] @@ -2160,6 +2191,15 @@ dependencies = [ "cc", ] +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -2418,7 +2458,7 @@ name = "polygomusic" version = "0.1.0" dependencies = [ "iced", - "svg", + "tokio", ] [[package]] @@ -2622,6 +2662,12 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -2924,12 +2970,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" -[[package]] -name = "svg" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94afda9cd163c04f6bee8b4bf2501c91548deae308373c436f36aeff3cf3c4a3" - [[package]] name = "svg_fmt" version = "0.4.5" @@ -3074,6 +3114,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokio" +version = "1.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +dependencies = [ + "backtrace", + "pin-project-lite", +] + [[package]] name = "toml_datetime" version = "0.6.9" diff --git a/Cargo.toml b/Cargo.toml index c75a9d3..8066058 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] -iced = { version = "0.13.1", features = ["canvas"] } -svg = "0.18.0" +iced = { version = "0.13.1", features = ["canvas", "tokio"] } +tokio = {version = "1.45.1", features = ["time"]} diff --git a/src/main.rs b/src/main.rs index 504ba96..2a83493 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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) { + ( + 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 { 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 canvas::Program for Circle { - // No internal state - type State = (); - - fn draw( - &self, - _state: &(), - renderer: &Renderer, - _theme: &Theme, - bounds: Rectangle, - _cursor: mouse::Cursor, - ) -> Vec { - // 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 { + time::every(Duration::from_millis(1)).map(|_| Message::Tick) } } diff --git a/src/polygon_draw.rs b/src/polygon_draw.rs new file mode 100644 index 0000000..5722469 --- /dev/null +++ b/src/polygon_draw.rs @@ -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 canvas::Program for PolygonFrame { + // No internal state + type State = (); + + fn draw( + &self, + _state: &(), + renderer: &Renderer, + _theme: &Theme, + bounds: Rectangle, + _cursor: mouse::Cursor, + ) -> Vec { + // 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()] + } +}