Compare commits
	
		
			No commits in common. "7c01b355a979243ab4edfc60218c132a12fe8fd9" and "b730f7640c7eaa86a37081ed07c2e1c75f9a30d6" have entirely different histories.
		
	
	
		
			7c01b355a9
			...
			b730f7640c
		
	
		
| @ -1,6 +0,0 @@ | |||||||
| # clipboard api is still unstable, so web-sys requires the below flag to be passed for copy (ctrl + c) to work |  | ||||||
| # https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html |  | ||||||
| # check status at https://developer.mozilla.org/en-US/docs/Web/API/Clipboard#browser_compatibility |  | ||||||
| # we don't use `[build]` because of rust analyzer's build cache invalidation https://github.com/emilk/eframe_template/issues/93 |  | ||||||
| [target.wasm32-unknown-unknown] |  | ||||||
| rustflags = ["--cfg=web_sys_unstable_apis"] |  | ||||||
							
								
								
									
										29
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,13 +1,22 @@ | |||||||
| # Mac stuff: | 
 | ||||||
| .DS_Store | .obsidian/* | ||||||
|  | .vscode/* | ||||||
|  | 
 | ||||||
|  | # ---> Rust | ||||||
|  | # Generated by Cargo | ||||||
|  | # will have compiled files and executables | ||||||
|  | debug/ | ||||||
|  | target/ | ||||||
|  | 
 | ||||||
|  | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries | ||||||
|  | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html | ||||||
|  | Cargo.lock | ||||||
|  | 
 | ||||||
|  | # These are backup files generated by rustfmt | ||||||
|  | **/*.rs.bk | ||||||
|  | 
 | ||||||
|  | # MSVC Windows builds of rustc generate these, which store debugging information | ||||||
|  | *.pdb | ||||||
| 
 | 
 | ||||||
| # trunk output folder | # trunk output folder | ||||||
| dist | dist | ||||||
| 
 |  | ||||||
| # Rust compile target directories: |  | ||||||
| target |  | ||||||
| target_ra |  | ||||||
| target_wasm |  | ||||||
| 
 |  | ||||||
| # https://github.com/lycheeverse/lychee |  | ||||||
| .lycheecache |  | ||||||
|  | |||||||
							
								
								
									
										2416
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2416
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										99
									
								
								Cargo.toml
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										99
									
								
								Cargo.toml
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @ -1,57 +1,42 @@ | |||||||
| [package] | [package] | ||||||
| name = "egui_circles" | name = "egui-circles" | ||||||
| version = "0.2.1" | version = "0.2.0" | ||||||
| authors = ["Andriy Djmil <andriy@djmil.dev>"] | authors = ["Andriy Djmil <andriy@djmil.dev>"] | ||||||
| edition = "2021" | edition = "2021" | ||||||
| include = ["LICENSE", "**/*.rs", "Cargo.toml"] | rust-version = "1.76" | ||||||
| rust-version = "1.76" | 
 | ||||||
| 
 | [package.metadata.docs.rs] | ||||||
| [package.metadata.docs.rs] | all-features = true | ||||||
| all-features = true | targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] | ||||||
| targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] | 
 | ||||||
| 
 | [dependencies] | ||||||
| [dependencies] | egui = "0.28" | ||||||
| egui = "0.28" | eframe = { version = "0.28", default-features = false, features = [ | ||||||
| eframe = { version = "0.28", default-features = false, features = [ | #   "accesskit",     # Make egui compatible with screen readers. NOTE: adds a lot of dependencies. | ||||||
| #   "accesskit",     # Make egui compatible with screen readers. NOTE: adds a lot of dependencies. |     "default_fonts", # Embed the default egui fonts. | ||||||
|     "default_fonts", # Embed the default egui fonts. |     "glow",          # Use the glow rendering backend. Alternative: "wgpu". | ||||||
|     "glow",          # Use the glow rendering backend. Alternative: "wgpu". | #   "persistence",   # Enable restoring app state when restarting the app. | ||||||
|     "persistence",   # Enable restoring app state when restarting the app. | ] } | ||||||
| ] } | log = "0.4" | ||||||
| log = "0.4" | emath  = "0.28.0" | ||||||
| emath  = "0.28.0" | rand = "0.8" | ||||||
| rand = "0.8" | getrandom = { version = "0.2", features = ["js"] } | ||||||
| getrandom = { version = "0.2", features = ["js"] } | 
 | ||||||
| 
 | # native: | ||||||
| # You only need serde if you want app persistence: | [target.'cfg(not(target_arch = "wasm32"))'.dependencies] | ||||||
| serde = { version = "1", features = ["derive"] } | env_logger = "0.10" | ||||||
| 
 | 
 | ||||||
| # native: | # web: | ||||||
| [target.'cfg(not(target_arch = "wasm32"))'.dependencies] | [target.'cfg(target_arch = "wasm32")'.dependencies] | ||||||
| env_logger = "0.10" | wasm-bindgen-futures = "0.4" | ||||||
| 
 | 
 | ||||||
| # web: | # to access the DOM (to hide the loading text) | ||||||
| [target.'cfg(target_arch = "wasm32")'.dependencies] | [target.'cfg(target_arch = "wasm32")'.dependencies.web-sys] | ||||||
| wasm-bindgen-futures = "0.4" | version = "0.3.4" | ||||||
| 
 | 
 | ||||||
| # to access the DOM (to hide the loading text) | [profile.release] | ||||||
| [target.'cfg(target_arch = "wasm32")'.dependencies.web-sys] | opt-level = 2 # fast and small wasm | ||||||
| version = "0.3.4" | 
 | ||||||
| 
 | # Optimize all dependencies even in debug builds: | ||||||
| [profile.release] | [profile.dev.package."*"] | ||||||
| opt-level = 2 # fast and small wasm | opt-level = 2 | ||||||
| 
 |  | ||||||
| # Optimize all dependencies even in debug builds: |  | ||||||
| [profile.dev.package."*"] |  | ||||||
| opt-level = 2 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| [patch.crates-io] |  | ||||||
| 
 |  | ||||||
| # If you want to use the bleeding edge version of egui and eframe: |  | ||||||
| # egui = { git = "https://github.com/emilk/egui", branch = "master" } |  | ||||||
| # eframe = { git = "https://github.com/emilk/egui", branch = "master" } |  | ||||||
| 
 |  | ||||||
| # If you fork https://github.com/emilk/egui you can test with: |  | ||||||
| # egui = { path = "../egui/crates/egui" } |  | ||||||
| # eframe = { path = "../egui/crates/eframe" } |  | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "eGUI Circles", |   "name": "eGUI Circles", | ||||||
|   "short_name": "egui-circles", |   "short_name": "circles", | ||||||
|   "icons": [ |   "icons": [ | ||||||
|     { |     { | ||||||
|       "src": "/icon-192.png", |       "src": "/icon-192.png", | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| var cacheName = 'egui_circles'; | var cacheName = 'egui-template-pwa'; | ||||||
| var filesToCache = [ | var filesToCache = [ | ||||||
|   './', |   './', | ||||||
|   './index.html', |   './index.html', | ||||||
|   './egui_circles.js', |   './eframe_template.js', | ||||||
|   './egui_circles_bg.wasm', |   './eframe_template_bg.wasm', | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| /* Start the service worker and cache all of the app's content */ | /* Start the service worker and cache all of the app's content */ | ||||||
|  | |||||||
| @ -9,3 +9,4 @@ ENTRYPOINT ["trunk"] | |||||||
| CMD ["serve"] | CMD ["serve"] | ||||||
| 
 | 
 | ||||||
| WORKDIR /egui-circles | WORKDIR /egui-circles | ||||||
|  | 
 | ||||||
							
								
								
									
										4
									
								
								docker/make-builder.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										4
									
								
								docker/make-builder.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  | set -euxo pipefail | ||||||
|  | 
 | ||||||
|  | docker build --tag egui-circles-builder:0.0.1 . | ||||||
							
								
								
									
										10
									
								
								docker/serve.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								docker/serve.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  | set -euo pipefail | ||||||
|  | 
 | ||||||
|  | PROJECT_NAME=egui-circles | ||||||
|  | 
 | ||||||
|  | docker run \ | ||||||
|  | 	--volume $(pwd)/..:/$PROJECT_NAME \ | ||||||
|  | 	--name vsc-$PROJECT_NAME          \ | ||||||
|  | 	-p 8080:8080                      \ | ||||||
|  | 	$PROJECT_NAME-builder:0.0.1 | ||||||
							
								
								
									
										24
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								index.html
									
									
									
									
									
								
							| @ -1,9 +1,9 @@ | |||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html> | <html> | ||||||
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | <meta http-equiv="Content-Type" charset="utf-8" /> | ||||||
| 
 | 
 | ||||||
| <!-- Disable zooming: --> | <!-- Disable zooming: --> | ||||||
| <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> | <meta name="viewport" content="width=device-width, initial-scale=1.5, user-scalable=no"> | ||||||
| 
 | 
 | ||||||
| <head> | <head> | ||||||
|     <!-- change this to your project name --> |     <!-- change this to your project name --> | ||||||
| @ -56,16 +56,15 @@ | |||||||
|             width: 100%; |             width: 100%; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /* Make canvas fill entire document: */ |         /* Position canvas in center-top: */ | ||||||
|         canvas { |         canvas { | ||||||
|             margin-right: auto; |             margin-right: auto; | ||||||
|             margin-left: auto; |             margin-left: auto; | ||||||
|             display: block; |             display: block; | ||||||
|             position: absolute; |             position: absolute; | ||||||
|             top: 0; |             top: 0%; | ||||||
|             left: 0; |             left: 50%; | ||||||
|             width: 100%; |             transform: translate(-50%, 0%); | ||||||
|             height: 100%; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         .centered { |         .centered { | ||||||
| @ -111,21 +110,14 @@ | |||||||
|                 transform: rotate(360deg); |                 transform: rotate(360deg); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|     </style> |     </style> | ||||||
| </head> | </head> | ||||||
| 
 | 
 | ||||||
| <body> | <body> | ||||||
|     <!-- The WASM code will resize the canvas dynamically --> |     <!-- The WASM code will resize the canvas dynamically --> | ||||||
|     <!-- the id is hardcoded in main.rs . so, make sure both match. --> |     <!-- the id is hardcoded in main.rs . so, make sure both match. --> | ||||||
|     <canvas id="the_canvas_id"></canvas> |     <canvas id="the_canvas_id" width="800" height="600"></canvas> | ||||||
| 
 |  | ||||||
|     <!-- the loading spinner will be removed in main.rs --> |  | ||||||
|     <div class="centered" id="loading_text"> |  | ||||||
|         <p style="font-size:16px"> |  | ||||||
|             Loading… |  | ||||||
|         </p> |  | ||||||
|         <div class="lds-dual-ring"></div> |  | ||||||
|     </div> |  | ||||||
| 
 | 
 | ||||||
|     <!--Register Service Worker. this will cache the wasm / js scripts for offline use (for PWA functionality). --> |     <!--Register Service Worker. this will cache the wasm / js scripts for offline use (for PWA functionality). --> | ||||||
|     <!-- Force refresh (Ctrl + F5) to load the latest files instead of cached files  --> |     <!-- Force refresh (Ctrl + F5) to load the latest files instead of cached files  --> | ||||||
|  | |||||||
							
								
								
									
										142
									
								
								src/app.rs
									
									
									
									
									
								
							
							
						
						
									
										142
									
								
								src/app.rs
									
									
									
									
									
								
							| @ -1,24 +1,25 @@ | |||||||
| use egui::{Color32, Stroke, Vec2}; | extern crate emath; | ||||||
| use rand::Rng; | 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; | use crate::circle::Circle; | ||||||
| 
 | 
 | ||||||
| /// We derive Deserialize/Serialize so we can persist app state on shutdown.
 |  | ||||||
| #[derive(serde::Deserialize, serde::Serialize)] |  | ||||||
| #[serde(default)] // if we add new fields, give them default values when deserializing old state
 |  | ||||||
| 
 |  | ||||||
| pub struct Simulation { | pub struct Simulation { | ||||||
|  |     circles: Vec<Circle>, | ||||||
|     circles_count: usize, |     circles_count: usize, | ||||||
| 
 | 
 | ||||||
|     #[serde(skip)] // This how you opt-out of serialization of a field
 |  | ||||||
|     circles: Vec<Circle>, |  | ||||||
|     #[serde(skip)] |  | ||||||
|     colors: Vec<egui::Color32>, |     colors: Vec<egui::Color32>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Default for Simulation { | impl Default for Simulation { | ||||||
|     fn default() -> Self { |     fn default() -> Self { | ||||||
|         Self {            
 |         Self { | ||||||
|             circles: Vec::new(), |             circles: Vec::new(), | ||||||
|             circles_count: 2, |             circles_count: 2, | ||||||
|             colors: Vec::new(), |             colors: Vec::new(), | ||||||
| @ -26,87 +27,21 @@ impl Default for Simulation { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Simulation { |  | ||||||
|     /// Called once before the first frame.
 |  | ||||||
|     pub fn new(cc: &eframe::CreationContext<'_>) -> Self { |  | ||||||
|         // This is also where you can customize the look and feel of egui using
 |  | ||||||
|         // `cc.egui_ctx.set_visuals` and `cc.egui_ctx.set_fonts`.
 |  | ||||||
| 
 |  | ||||||
|         // Looks better on 4k montior
 |  | ||||||
|         cc.egui_ctx.set_pixels_per_point(1.5); |  | ||||||
| 
 |  | ||||||
|         // Load previous app state (if any).
 |  | ||||||
|         // Note that you must enable the `persistence` feature for this to work.
 |  | ||||||
|         if let Some(storage) = cc.storage { |  | ||||||
|             return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         Default::default() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl eframe::App for Simulation { | impl eframe::App for Simulation { | ||||||
|     /// Called by the frame work to save state before shutdown.
 |  | ||||||
|     fn save(&mut self, storage: &mut dyn eframe::Storage) { |  | ||||||
|         eframe::set_value(storage, eframe::APP_KEY, self); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /// Called each time the UI needs repainting, which may be many times per second.
 |  | ||||||
|     fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { |     fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { | ||||||
|         // Put your widgets into a `SidePanel`, `TopBottomPanel`, `CentralPanel`, `Window` or `Area`.
 |         // Looks better on 4k montior
 | ||||||
|         // For inspiration and more examples, go to https://emilk.github.io/egui
 |         ctx.set_pixels_per_point(1.5); | ||||||
| 
 |  | ||||||
|         egui::TopBottomPanel::top("top_panel").show(ctx, |ui| { |  | ||||||
|             // The top panel is often a good place for a menu bar:
 |  | ||||||
| 
 |  | ||||||
|             egui::menu::bar(ui, |ui| { |  | ||||||
|                 // NOTE: no File->Quit on web pages!
 |  | ||||||
|                 let is_web = cfg!(target_arch = "wasm32"); |  | ||||||
|                 if !is_web { |  | ||||||
|                     ui.menu_button("File", |ui| { |  | ||||||
|                         if ui.button("Quit").clicked() { |  | ||||||
|                             ctx.send_viewport_cmd(egui::ViewportCommand::Close); |  | ||||||
|                         } |  | ||||||
|                     }); |  | ||||||
|                     ui.add_space(16.0); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 egui::widgets::global_dark_light_mode_buttons(ui); |  | ||||||
| 
 |  | ||||||
|                 ui.with_layout(egui::Layout::top_down(egui::Align::RIGHT), |ui| { |  | ||||||
|                     ui.horizontal(|ui| { |  | ||||||
|                         ui.spacing_mut().item_spacing.x = 4.0; |  | ||||||
|                         ui.hyperlink_to( |  | ||||||
|                             "source code", |  | ||||||
|                             "https://gitea.djmil.dev/djmil/egui-circles", |  | ||||||
|                         ); |  | ||||||
|                         ui.label("rust"); |  | ||||||
|                     }); |  | ||||||
|                 }); |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|         egui::CentralPanel::default().show(ctx, |ui| { |         egui::CentralPanel::default().show(ctx, |ui| { | ||||||
|             // The central panel the region left after adding TopPanel's and SidePanel's
 |             if ui.button("halt").clicked() { | ||||||
|  |                 self.circles.iter_mut().for_each(|c| (*c).v = Vec2{x: 0.0, y: 0.0}); | ||||||
|  |             }; | ||||||
| 
 | 
 | ||||||
|             // Simulatiom
 |             if ui.button("push").clicked() { | ||||||
|             ui.horizontal(|ui| { |                 self.circles.iter_mut().for_each(|c| (*c).v = Vec2{ | ||||||
|                 ui.label("Click on circles or press"); |                     x: rand::thread_rng().gen_range(-2.0..2.0), | ||||||
| 
 |                     y: rand::thread_rng().gen_range(-2.0..2.0)}); | ||||||
|                 if ui.button("push").clicked() { |             }; | ||||||
|                     self.circles.iter_mut().for_each(|c| (*c).v = Vec2{ |  | ||||||
|                         x: rand::thread_rng().gen_range(-4.0..4.0), |  | ||||||
|                         y: rand::thread_rng().gen_range(-4.0..4.0)}); |  | ||||||
|                 }; |  | ||||||
| 
 |  | ||||||
|                 ui.label("or"); |  | ||||||
| 
 |  | ||||||
|                 if ui.button("halt").clicked() { |  | ||||||
|                     self.circles.iter_mut().for_each(|c| (*c).v = Vec2{x: 0.0, y: 0.0}); |  | ||||||
|                 }; |  | ||||||
| 
 |  | ||||||
|                 ui.label("buttons"); |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             ui.add(egui::Slider::new(&mut self.circles_count, 0..=25).text("circles count")); |             ui.add(egui::Slider::new(&mut self.circles_count, 0..=25).text("circles count")); | ||||||
| 
 | 
 | ||||||
| @ -118,10 +53,10 @@ impl eframe::App for Simulation { | |||||||
|                     self.circles.push(Circle::default()); |                     self.circles.push(Circle::default()); | ||||||
|                     self.colors.push( |                     self.colors.push( | ||||||
|                         egui::Color32::from_rgba_premultiplied( |                         egui::Color32::from_rgba_premultiplied( | ||||||
|                             rand::thread_rng().gen_range(64..255), |                             rand::thread_rng().gen_range(0..255), | ||||||
|                             rand::thread_rng().gen_range(64..255), |                             rand::thread_rng().gen_range(0..255), | ||||||
|                             rand::thread_rng().gen_range(64..255), |                             rand::thread_rng().gen_range(0..255), | ||||||
|                             128) |                             64) | ||||||
|                         ); |                         ); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -157,19 +92,9 @@ impl eframe::App for Simulation { | |||||||
|                     self.circles[i].c, 
 |                     self.circles[i].c, 
 | ||||||
|                     self.circles[i].r, 
 |                     self.circles[i].r, 
 | ||||||
|                 self.colors[i] /*Color32::TRANSPARENT*/, 
 |                 self.colors[i] /*Color32::TRANSPARENT*/, 
 | ||||||
|                     Stroke{width: 2.0, color: Color32::from_rgb(200, 255, 255)} |                     Stroke{width: 2.0, color: Color32::from_rgb(255, 255, 255)} | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|             // End simultion
 |  | ||||||
| 
 |  | ||||||
|             ui.separator(); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| { |  | ||||||
|                 powered_by_egui_and_eframe(ui); |  | ||||||
|                 egui::warn_if_debug_build(ui); |  | ||||||
|             }); |  | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         for circle in &mut self.circles { |         for circle in &mut self.circles { | ||||||
| @ -196,22 +121,9 @@ impl eframe::App for Simulation { | |||||||
| 
 | 
 | ||||||
|         // This is how to go into continuous mode - uncomment this to see example of continuous mode
 |         // This is how to go into continuous mode - uncomment this to see example of continuous mode
 | ||||||
|         ctx.request_repaint(); |         ctx.request_repaint(); | ||||||
| 
 |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn powered_by_egui_and_eframe(ui: &mut egui::Ui) { |  | ||||||
|     ui.horizontal(|ui| { |  | ||||||
|         ui.spacing_mut().item_spacing.x = 0.0; |  | ||||||
|         ui.label("Powered by "); |  | ||||||
|         ui.hyperlink_to("egui", "https://github.com/emilk/egui"); |  | ||||||
|         ui.label(" and "); |  | ||||||
|         ui.hyperlink_to( |  | ||||||
|             "eframe", |  | ||||||
|             "https://github.com/emilk/egui/tree/master/crates/eframe", |  | ||||||
|         ); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| fn collision(c1: &Circle, c2: &Circle) -> (Vec2, Vec2) { | fn collision(c1: &Circle, c2: &Circle) -> (Vec2, Vec2) { | ||||||
|     let m1 = c1.r; |     let m1 = c1.r; | ||||||
| @ -256,3 +168,5 @@ fn collision(c1: &Circle, c2: &Circle) -> (Vec2, Vec2) { | |||||||
|         vec2n + vec2t |         vec2n + vec2t | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | //}
 | ||||||
|  | |||||||
| @ -1,5 +1,10 @@ | |||||||
| use egui::{Pos2, Rect, Vec2}; | extern crate emath; | ||||||
| use rand::Rng; | 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; | pub static FRICTION: f32 = 0.995; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +0,0 @@ | |||||||
| #![warn(clippy::all, rust_2018_idioms)] |  | ||||||
| 
 |  | ||||||
| mod app; |  | ||||||
| pub use app::Simulation; |  | ||||||
| 
 |  | ||||||
| mod circle; |  | ||||||
							
								
								
									
										127
									
								
								src/main.rs
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										127
									
								
								src/main.rs
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @ -1,63 +1,64 @@ | |||||||
| #![warn(clippy::all, rust_2018_idioms)] | mod app; | ||||||
| #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
 | mod circle; | ||||||
| 
 | 
 | ||||||
| // When compiling natively:
 | // When compiling natively:
 | ||||||
| #[cfg(not(target_arch = "wasm32"))] | #[cfg(not(target_arch = "wasm32"))] | ||||||
| fn main() -> eframe::Result { | fn main() -> eframe::Result<()> { | ||||||
|     env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
 |     //env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
 | ||||||
| 
 | 
 | ||||||
|     let native_options = eframe::NativeOptions { |     let native_options = eframe::NativeOptions { | ||||||
|         viewport: egui::ViewportBuilder::default() |         viewport: eframe::egui::ViewportBuilder::default() | ||||||
|             .with_inner_size([800.0, 600.0]) |             .with_inner_size([800.0, 600.0]) | ||||||
|             .with_min_inner_size([300.0, 220.0]) |             .with_min_inner_size([300.0, 220.0]) | ||||||
|             .with_icon( |             .with_icon( 
 | ||||||
|                 // NOTE: Adding an icon is optional
 |                 // NOTE: Adding an icon is optional
 | ||||||
|                 eframe::icon_data::from_png_bytes(&include_bytes!("../assets/icon-192.png")[..]) |                 eframe::icon_data::from_png_bytes(&include_bytes!("../assets/icon-192.png")[..]) | ||||||
|                     .expect("Failed to load icon"), |                     .expect("Failed to load icon"), | ||||||
|             ), |             ), | ||||||
|         ..Default::default() |         ..Default::default() | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     eframe::run_native( |     eframe::run_native( | ||||||
|         "eGUI Circles", |         "egui-circles", | ||||||
|         native_options, |         native_options, | ||||||
|         Box::new(|cc| Ok(Box::new(egui_circles::Simulation::new(cc)))), |         Box::new(|_| Ok(Box::<crate::app::Simulation>::default())), | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // When compiling to web using trunk:
 | // When compiling to web using trunk:
 | ||||||
| #[cfg(target_arch = "wasm32")] | #[cfg(target_arch = "wasm32")] | ||||||
| fn main() { | fn main() { | ||||||
|     // Redirect `log` message to `console.log` and friends:
 |     // Redirect `log` message to `console.log` and friends:
 | ||||||
|     eframe::WebLogger::init(log::LevelFilter::Debug).ok(); |     eframe::WebLogger::init(log::LevelFilter::Debug).ok(); | ||||||
| 
 | 
 | ||||||
|     let web_options = eframe::WebOptions::default(); |     let web_options = eframe::WebOptions::default(); | ||||||
| 
 | 
 | ||||||
|     wasm_bindgen_futures::spawn_local(async { |     wasm_bindgen_futures::spawn_local(async { | ||||||
|         let start_result = eframe::WebRunner::new() |         let start_result = eframe::WebRunner::new() | ||||||
|             .start( |             .start( | ||||||
|                 "the_canvas_id", |                 "the_canvas_id", | ||||||
|                 web_options, |                 web_options, | ||||||
|                 Box::new(|cc| Ok(Box::new(egui_circles::Simulation::new(cc)))), |                 //Box::new(|cc| Ok(Box::new(eframe_template::TemplateApp::new(cc)))),
 | ||||||
|             ) |                 Box::new(|_| Ok(Box::<crate::app::Simulation>::default())), | ||||||
|             .await; |             ) | ||||||
| 
 |             .await; | ||||||
|         // Remove the loading text and spinner:
 | 
 | ||||||
|         let loading_text = web_sys::window() |         // Remove the loading text and spinner:
 | ||||||
|             .and_then(|w| w.document()) |         let loading_text = web_sys::window() | ||||||
|             .and_then(|d| d.get_element_by_id("loading_text")); |             .and_then(|w| w.document()) | ||||||
|         if let Some(loading_text) = loading_text { |             .and_then(|d| d.get_element_by_id("loading_text")); | ||||||
|             match start_result { |         if let Some(loading_text) = loading_text { | ||||||
|                 Ok(_) => { |             match start_result { | ||||||
|                     loading_text.remove(); |                 Ok(_) => { | ||||||
|                 } |                     loading_text.remove(); | ||||||
|                 Err(e) => { |                 } | ||||||
|                     loading_text.set_inner_html( |                 Err(e) => { | ||||||
|                         "<p> The app has crashed. See the developer console for details. </p>", |                     loading_text.set_inner_html( | ||||||
|                     ); |                         "<p> The app has crashed. See the developer console for details. </p>", | ||||||
|                     panic!("Failed to start eframe: {e:?}"); |                     ); | ||||||
|                 } |                     panic!("Failed to start eframe: {e:?}"); | ||||||
|             } |                 } | ||||||
|         } |             } | ||||||
|     }); |         } | ||||||
| } |     }); | ||||||
|  | } | ||||||
| @ -1,40 +0,0 @@ | |||||||
| #!/usr/bin/env bash |  | ||||||
| set -euo pipefail |  | ||||||
| 
 |  | ||||||
| NAME=egui-circles |  | ||||||
| BUILDER=djmil/$NAME-builder:0.0.1 |  | ||||||
| TRAGET=$NAME-wasm32 |  | ||||||
| 
 |  | ||||||
| has_docker_image() { |  | ||||||
|    docker manifest inspect $1 |  | ||||||
| } &> /dev/null |  | ||||||
| 
 |  | ||||||
| has_docker_container() { |  | ||||||
| 	docker container inspect $1 |  | ||||||
| } &> /dev/null |  | ||||||
| 
 |  | ||||||
| if ! has_docker_image $BUILDER; then |  | ||||||
| 	echo "Docker $BUILDER was not found" |  | ||||||
| 	 |  | ||||||
| 	read -p "Would you like to create builder image (y/n)? " |  | ||||||
| 	case "$REPLY" in  |  | ||||||
| 	y|Y ) |  | ||||||
| 		docker build --tag $BUILDER . ;; |  | ||||||
|   	* ) |  | ||||||
| 		exit 1 ;; |  | ||||||
| 	esac |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| echo "Initiate WASM32 target build.." |  | ||||||
| 
 |  | ||||||
| if has_docker_container $TRAGET; then |  | ||||||
| 	docker start \ |  | ||||||
| 		$TRAGET \ |  | ||||||
| 		--attach |  | ||||||
| else |  | ||||||
| 	docker run \ |  | ||||||
| 		--volume $(pwd):/$NAME \ |  | ||||||
| 		--name $TRAGET            \ |  | ||||||
| 		$BUILDER \ |  | ||||||
| 		build --release --public-url /$NAME --verbose |  | ||||||
| fi |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user