From ec89736b732a16ee729860dfdfd53e43a7d3f10f Mon Sep 17 00:00:00 2001 From: djmil Date: Wed, 3 Jul 2024 20:31:14 +0200 Subject: [PATCH 1/3] split main and app sources --- src/app.rs | 169 +++++++++++++++++++++++++++++++++++++++++++++ src/circle.rs | 99 +++++++++++++-------------- src/main.rs | 186 ++++---------------------------------------------- 3 files changed, 231 insertions(+), 223 deletions(-) create mode 100644 src/app.rs diff --git a/src/app.rs b/src/app.rs new file mode 100644 index 0000000..cbc47b5 --- /dev/null +++ b/src/app.rs @@ -0,0 +1,169 @@ +use emath::Vec2; +use eframe::egui; +use egui::Color32; +use egui::Stroke; +use rand::Rng; + +use crate::circle::Circle; + +pub struct Simulation { + circles: Vec, + circles_count: usize, + + colors: Vec, +} + +impl Default for Simulation { + fn default() -> Self { + Self { + circles: Vec::new(), + circles_count: 2, + colors: Vec::new(), + } + } +} + +impl eframe::App for Simulation { + fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { + // Looks better on 4k montior + ctx.set_pixels_per_point(1.5); + + egui::CentralPanel::default().show(ctx, |ui| { + if ui.button("halt").clicked() { + self.circles.iter_mut().for_each(|c| (*c).v = Vec2{x: 0.0, y: 0.0}); + }; + + if ui.button("push").clicked() { + self.circles.iter_mut().for_each(|c| (*c).v = Vec2{ + x: rand::thread_rng().gen_range(-2.0..2.0), + y: rand::thread_rng().gen_range(-2.0..2.0)}); + }; + + + ui.add(egui::Slider::new(&mut self.circles_count, 0..=25).text("circles count")); + + let diff = (self.circles.len() as i32) - (self.circles_count as i32); + if diff > 0 { + self.circles.truncate(self.circles_count); + } else { + for _ in diff..0 { + self.circles.push(Circle::default()); + self.colors.push( + egui::Color32::from_rgba_premultiplied( + rand::thread_rng().gen_range(0..255), + rand::thread_rng().gen_range(0..255), + rand::thread_rng().gen_range(0..255), + 64) + ); + } + } + + let painter = ui.painter(); + + let (hover_pos, any_down, any_released) = ctx.input(|input| ( + input.pointer.hover_pos(), + input.pointer.any_down(), + input.pointer.any_released() + )); + + if let Some(mousepos) = hover_pos { + + self.circles.iter_mut().for_each(|circle|{ + let d = circle.c - mousepos; + if d.length() < circle.r { + if any_down { + painter.line_segment( + [circle.c, circle.c +d], + Stroke{width: 1.0, color: Color32::from_rgb(128, 255, 255)}); + } + + if any_released { + circle.v += d.normalized() * (d.length() / circle.r) * 8.0; + } + } + }); + } + + for i in 0..self.circles_count { + painter.circle( + self.circles[i].c, + self.circles[i].r, + self.colors[i] /*Color32::TRANSPARENT*/, + Stroke{width: 2.0, color: Color32::from_rgb(255, 255, 255)} + ); + } + }); + + for circle in &mut self.circles { + circle.apply_force(&ctx.used_rect()); + } + + // Naive N^2 Colition detection + // Optimization https://en.wikipedia.org/wiki/Sweep_and_prune + for i in 0..self.circles_count { + for j in i+1..self.circles_count { + + if (i + j) % 3 == 0 { + continue; // skip collsions for every third ball + } + + let dc = self.circles[i].c - self.circles[j].c; + let dr = self.circles[i].r + self.circles[j].r; + + if dc.length() < dr { + (self.circles[i].v, self.circles[j].v) = collision(&self.circles[i], &self.circles[j]); + } + } + } + + // This is how to go into continuous mode - uncomment this to see example of continuous mode + ctx.request_repaint(); + } +} + + +fn collision(c1: &Circle, c2: &Circle) -> (Vec2, Vec2) { + let m1 = c1.r; + let m2 = c2.r; + + // collision normal + let n = Vec2{ + x: c2.c.x - c1.c.x, + y: c2.c.y - c1.c.y + }; + + // normal vector unit + let un = n.normalized(); + + // collision tangen + let ut = Vec2{x: -un.y, y: un.x}; + + // 3 + let v1n = un.dot(c1.v); + let v1t = ut.dot(c1.v); + + let v2n = un.dot(c2.v); + let v2t = ut.dot(c2.v); + + // 4 + let v1t_new = v1t; + let v2t_new = v2t; + + // 5 + let v1n_new = (v1n * (m1 - m2) + 2.0 * m2 * v2n) / (m1 + m2); + let v2n_new = (v2n * (m2 - m1) + 2.0 * m1 * v1n) / (m1 + m2); + + // 6 + let vec1n = v1n_new * un; + let vec1t = v1t_new * ut; + + let vec2n = v2n_new * un; + let vec2t = v2t_new * ut; + + return ( + vec1n + vec1t, + vec2n + vec2t + ); +} + +//} diff --git a/src/circle.rs b/src/circle.rs index e0c892c..8be5263 100644 --- a/src/circle.rs +++ b/src/circle.rs @@ -1,58 +1,55 @@ -pub mod circle { +use emath::Vec2; +use emath::Pos2; +use emath::Rect; +use rand::Rng; - use emath::Vec2; - use emath::Pos2; - use emath::Rect; - use rand::Rng; +pub static FRICTION: f32 = 0.995; - pub static FRICTION: f32 = 0.995; +pub struct Circle { + pub v: Vec2, + pub c: Pos2, + pub r: f32, +} - pub struct Circle { - pub v: Vec2, - pub c: Pos2, - pub r: f32, - } - - impl Default for Circle { - fn default() -> Self { - let r = rand::thread_rng().gen_range(20.0..50.0); - Self { - r: r, - c: Pos2 { - x: rand::thread_rng().gen_range(r..400.0-r), - y: rand::thread_rng().gen_range(r..400.0-r)}, - v: Vec2 { - x: rand::thread_rng().gen_range(-2.0..2.0), - y: rand::thread_rng().gen_range(-2.0..2.0)}, - } - } - } - - impl Circle { - pub fn apply_force(&mut self, bb: &Rect) { - self.v *= FRICTION; - self.c += self.v; - - if self.v.x > 0.0 { - if self.c.x + self.r > bb.right() { - self.v.x *= -1.0 - } - } else { - if self.c.x - self.r < bb.left() { - self.v.x *= -1.0 - } - } - - if self.v.y > 0.0 { - if self.c.y + self.r > bb.bottom() { - self.v.y *= -1.0 - } - } else { - if self.c.y - self.r < bb.top() { - self.v.y *= -1.0 - } - } +impl Default for Circle { + fn default() -> Self { + let r = rand::thread_rng().gen_range(20.0..50.0); + Self { + r: r, + c: Pos2 { + x: rand::thread_rng().gen_range(r..400.0-r), + y: rand::thread_rng().gen_range(r..400.0-r)}, + v: Vec2 { + x: rand::thread_rng().gen_range(-2.0..2.0), + y: rand::thread_rng().gen_range(-2.0..2.0)}, } } } +impl Circle { + pub fn apply_force(&mut self, bb: &Rect) { + self.v *= FRICTION; + self.c += self.v; + + if self.v.x > 0.0 { + if self.c.x + self.r > bb.right() { + self.v.x *= -1.0 + } + } else { + if self.c.x - self.r < bb.left() { + self.v.x *= -1.0 + } + } + + if self.v.y > 0.0 { + if self.c.y + self.r > bb.bottom() { + self.v.y *= -1.0 + } + } else { + if self.c.y - self.r < bb.top() { + self.v.y *= -1.0 + } + } + } + +} diff --git a/src/main.rs b/src/main.rs index d2b0b9c..cd5c5f3 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,182 +1,24 @@ -use emath::Vec2; -use eframe::egui; -use egui::Color32; -use egui::Stroke; -use rand::Rng; - +mod app; mod circle; -pub use circle::circle::Circle; - -struct ExampleApp { - circles: Vec, - circles_count: usize, - - colors: Vec, -} - -impl ExampleApp { - fn name() -> &'static str { - "egui-circles" - } -} - -impl Default for ExampleApp { - fn default() -> Self { - Self { - circles: Vec::new(), - circles_count: 2, - colors: Vec::new(), - } - } -} - -impl eframe::App for ExampleApp { - fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - // Looks better on 4k montior - ctx.set_pixels_per_point(1.5); - - egui::CentralPanel::default().show(ctx, |ui| { - if ui.button("halt").clicked() { - //frame.quit() - self.circles.iter_mut().for_each(|c| (*c).v = Vec2{x: 0.0, y: 0.0}); - }; - - if ui.button("push").clicked() { - self.circles.iter_mut().for_each(|c| (*c).v = Vec2{ - x: rand::thread_rng().gen_range(-2.0..2.0), - y: rand::thread_rng().gen_range(-2.0..2.0)}); - }; - - - ui.add(egui::Slider::new(&mut self.circles_count, 0..=25).text("circles count")); - let diff = (self.circles.len() as i32) - (self.circles_count as i32); - if diff > 0 { - self.circles.truncate(self.circles_count); - } else { - for _ in diff..0 { - self.circles.push(Circle::default()); - self.colors.push( - egui::Color32::from_rgba_premultiplied( - rand::thread_rng().gen_range(0..255), - rand::thread_rng().gen_range(0..255), - rand::thread_rng().gen_range(0..255), - 64) - ); - } - } - - let painter = ui.painter(); - - let (hover_pos, any_down, any_released) = ctx.input(|input| (input.pointer.hover_pos(), input.pointer.any_down(), input.pointer.any_released())); - - if let Some(mousepos) = hover_pos { - - self.circles.iter_mut().for_each(|circle|{ - let d = (*circle).c - mousepos; - if d.length() < (*circle).r { - if any_down { - painter.line_segment( - [(*circle).c, (*circle).c +d], - Stroke{width: 1.0, color: Color32::from_rgb(128, 255, 255)}); - } - - if any_released { - (*circle).v += d.normalized() * (d.length() / (*circle).r) *8.0; - } - } - }); - } - - for i in 0..self.circles_count { - painter.circle( - self.circles[i].c, - self.circles[i].r, - self.colors[i] /*Color32::TRANSPARENT*/, - Stroke{width: 2.0, color: Color32::from_rgb(255, 255, 255)} - ); - } - }); - - for circle in &mut self.circles { - (*circle).apply_force(&ctx.used_rect()); - } - - // Naive N^2 Colition detection - // Optimization https://en.wikipedia.org/wiki/Sweep_and_prune - for i in 0..self.circles_count { - for j in i+1..self.circles_count { - - if (i + j) % 3 == 0 { - continue; // skip collsions for every third ball - } - - let dc = self.circles[i].c - self.circles[j].c; - let dr = self.circles[i].r + self.circles[j].r; - - if dc.length() < dr { - (self.circles[i].v, self.circles[j].v) = collision(&self.circles[i], &self.circles[j]); - } - } - } - - // This is how to go into continuous mode - uncomment this to see example of continuous mode - ctx.request_repaint(); - } -} fn main() -> eframe::Result<()> { + //env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`). + let native_options = eframe::NativeOptions { - viewport: egui::ViewportBuilder::default().with_inner_size((800.0, 600.0)), - ..eframe::NativeOptions::default() + viewport: eframe::egui::ViewportBuilder::default() + .with_inner_size([800.0, 600.0]) + .with_min_inner_size([300.0, 220.0]) + .with_icon( + // NOTE: Adding an icon is optional + eframe::icon_data::from_png_bytes(&include_bytes!("../assets/icon-256.png")[..]) + .expect("Failed to load icon"), + ), + ..Default::default() }; eframe::run_native( - ExampleApp::name(), + "egui-circles", native_options, - Box::new(|_| Box::::default()), + Box::new(|_| Box::::default()), ) } - -fn collision(c1: &Circle, c2: &Circle) -> (Vec2, Vec2) { - let m1 = c1.r; - let m2 = c2.r; - - // collision normal - let n = Vec2{ - x: c2.c.x - c1.c.x, - y: c2.c.y - c1.c.y - }; - - // normal vector unit - let un = n.normalized(); - - // collision tangen - let ut = Vec2{x: -un.y, y: un.x}; - - // 3 - let v1n = un.dot(c1.v); - let v1t = ut.dot(c1.v); - - let v2n = un.dot(c2.v); - let v2t = ut.dot(c2.v); - - // 4 - let v1t_new = v1t; - let v2t_new = v2t; - - // 5 - let v1n_new = (v1n * (m1 - m2) + 2.0 * m2 * v2n) / (m1 + m2); - let v2n_new = (v2n * (m2 - m1) + 2.0 * m1 * v1n) / (m1 + m2); - - // 6 - let vec1n = v1n_new * un; - let vec1t = v1t_new * ut; - - let vec2n = v2n_new * un; - let vec2t = v2t_new * ut; - - return ( - vec1n + vec1t, - vec2n + vec2t - ); -} \ No newline at end of file -- 2.45.2 From 4a7adc6a898d1f4eab986181b0871741ea3f7688 Mon Sep 17 00:00:00 2001 From: djmil Date: Wed, 3 Jul 2024 22:22:53 +0200 Subject: [PATCH 2/3] web assembly + trunk --- .gitignore | 2 + Cargo.toml | 42 +++++++++++++-- assets/sw.js | 25 +++++++++ index.html | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/app.rs | 15 +++--- src/circle.rs | 11 ++-- src/main.rs | 42 ++++++++++++++- 7 files changed, 261 insertions(+), 16 deletions(-) create mode 100644 assets/sw.js create mode 100644 index.html diff --git a/.gitignore b/.gitignore index a1a5044..79dc8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ Cargo.lock # MSVC Windows builds of rustc generate these, which store debugging information *.pdb +# trunk output folder +dist diff --git a/Cargo.toml b/Cargo.toml index 8057ffe..0c627f4 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,42 @@ [package] name = "egui-circles" -version = "0.1.0" +version = "0.2.0" +authors = ["Andriy Djmil "] edition = "2021" -rust-version = "1.56" +rust-version = "1.76" + +[package.metadata.docs.rs] +all-features = true +targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] [dependencies] -eframe = "0.24.0" # Gives us egui, epi and web+native backends -emath = "0.24.0" -rand = "0.8" \ No newline at end of file +egui = "0.28" +eframe = { version = "0.28", default-features = false, features = [ +# "accesskit", # Make egui compatible with screen readers. NOTE: adds a lot of dependencies. + "default_fonts", # Embed the default egui fonts. + "glow", # Use the glow rendering backend. Alternative: "wgpu". +# "persistence", # Enable restoring app state when restarting the app. +] } +log = "0.4" +emath = "0.28.0" +rand = "0.8" +getrandom = { version = "0.2", features = ["js"] } + +# native: +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +env_logger = "0.10" + +# web: +[target.'cfg(target_arch = "wasm32")'.dependencies] +wasm-bindgen-futures = "0.4" + +# to access the DOM (to hide the loading text) +[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys] +version = "0.3.4" + +[profile.release] +opt-level = 2 # fast and small wasm + +# Optimize all dependencies even in debug builds: +[profile.dev.package."*"] +opt-level = 2 diff --git a/assets/sw.js b/assets/sw.js new file mode 100644 index 0000000..7ecd229 --- /dev/null +++ b/assets/sw.js @@ -0,0 +1,25 @@ +var cacheName = 'egui-template-pwa'; +var filesToCache = [ + './', + './index.html', + './eframe_template.js', + './eframe_template_bg.wasm', +]; + +/* Start the service worker and cache all of the app's content */ +self.addEventListener('install', function (e) { + e.waitUntil( + caches.open(cacheName).then(function (cache) { + return cache.addAll(filesToCache); + }) + ); +}); + +/* Serve cached content when offline */ +self.addEventListener('fetch', function (e) { + e.respondWith( + caches.match(e.request).then(function (response) { + return response || fetch(e.request); + }) + ); +}); diff --git a/index.html b/index.html new file mode 100644 index 0000000..ba10e11 --- /dev/null +++ b/index.html @@ -0,0 +1,140 @@ + + + + + + + + + + eframe template + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app.rs b/src/app.rs index cbc47b5..f936714 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,8 +1,12 @@ -use emath::Vec2; -use eframe::egui; -use egui::Color32; -use egui::Stroke; -use rand::Rng; +extern crate emath; +extern crate rand; +extern crate eframe; + +use self::emath::Vec2; +use self::eframe::egui; +use self::egui::Color32; +use self::egui::Stroke; +use self::rand::Rng; use crate::circle::Circle; @@ -39,7 +43,6 @@ impl eframe::App for Simulation { y: rand::thread_rng().gen_range(-2.0..2.0)}); }; - ui.add(egui::Slider::new(&mut self.circles_count, 0..=25).text("circles count")); let diff = (self.circles.len() as i32) - (self.circles_count as i32); diff --git a/src/circle.rs b/src/circle.rs index 8be5263..f4508f4 100644 --- a/src/circle.rs +++ b/src/circle.rs @@ -1,7 +1,10 @@ -use emath::Vec2; -use emath::Pos2; -use emath::Rect; -use rand::Rng; +extern crate emath; +extern crate rand; + +use self::emath::Vec2; +use self::emath::Pos2; +use self::emath::Rect; +use self::rand::Rng; pub static FRICTION: f32 = 0.995; diff --git a/src/main.rs b/src/main.rs index cd5c5f3..a3501a3 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ mod app; mod circle; +// When compiling natively: +#[cfg(not(target_arch = "wasm32"))] fn main() -> eframe::Result<()> { //env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`). @@ -19,6 +21,44 @@ fn main() -> eframe::Result<()> { eframe::run_native( "egui-circles", native_options, - Box::new(|_| Box::::default()), + Box::new(|_| Ok(Box::::default())), ) } + +// When compiling to web using trunk: +#[cfg(target_arch = "wasm32")] +fn main() { + // Redirect `log` message to `console.log` and friends: + eframe::WebLogger::init(log::LevelFilter::Debug).ok(); + + let web_options = eframe::WebOptions::default(); + + wasm_bindgen_futures::spawn_local(async { + let start_result = eframe::WebRunner::new() + .start( + "the_canvas_id", + web_options, + //Box::new(|cc| Ok(Box::new(eframe_template::TemplateApp::new(cc)))), + Box::new(|_| Ok(Box::::default())), + ) + .await; + + // Remove the loading text and spinner: + let loading_text = web_sys::window() + .and_then(|w| w.document()) + .and_then(|d| d.get_element_by_id("loading_text")); + if let Some(loading_text) = loading_text { + match start_result { + Ok(_) => { + loading_text.remove(); + } + Err(e) => { + loading_text.set_inner_html( + "

The app has crashed. See the developer console for details.

", + ); + panic!("Failed to start eframe: {e:?}"); + } + } + } + }); +} \ No newline at end of file -- 2.45.2 From fec4f55bc351e0ee8f33a09656f562264d6be721 Mon Sep 17 00:00:00 2001 From: djmil Date: Thu, 11 Jul 2024 22:14:27 +0200 Subject: [PATCH 3/3] assets --- assets/favicon.ico | Bin 0 -> 15406 bytes assets/icon-192.png | Bin 0 -> 26781 bytes assets/manifest.json | 17 +++++++++++++++++ index.html | 12 ++++-------- src/main.rs | 2 +- 5 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 assets/favicon.ico create mode 100644 assets/icon-192.png create mode 100644 assets/manifest.json diff --git a/assets/favicon.ico b/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b205b42ef09ffbadd3fa0c636ed20b51d4c8f50c GIT binary patch literal 15406 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 literal 0 HcmV?d00001 diff --git a/assets/icon-192.png b/assets/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..d8e9760ae61b37069ce481ee9296f5b46f3c75ba GIT binary patch literal 26781 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 - + - + - eframe template + egui Circles @@ -19,14 +19,10 @@ - - - - + - diff --git a/src/main.rs b/src/main.rs index a3501a3..bc29e8f 100755 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ fn main() -> eframe::Result<()> { .with_min_inner_size([300.0, 220.0]) .with_icon( // NOTE: Adding an icon is optional - eframe::icon_data::from_png_bytes(&include_bytes!("../assets/icon-256.png")[..]) + eframe::icon_data::from_png_bytes(&include_bytes!("../assets/icon-192.png")[..]) .expect("Failed to load icon"), ), ..Default::default() -- 2.45.2