From bd8184b50c81d1053f406ab076a94e101cb98314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Thu, 25 May 2023 14:38:33 +0200 Subject: [PATCH 1/6] addd an egui example --- README.md | 7 +- templates/apps/egui/.gitignore.hbs | 10 ++ templates/apps/egui/Cargo.toml.hbs | 38 ++++ templates/apps/egui/README.md | 5 + templates/apps/egui/gen/bin/desktop.rs.hbs | 4 + templates/apps/egui/src/lib.rs | 170 ++++++++++++++++++ .../app/src/main/res/values/styles.xml.hbs | 1 + 7 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 templates/apps/egui/.gitignore.hbs create mode 100644 templates/apps/egui/Cargo.toml.hbs create mode 100644 templates/apps/egui/README.md create mode 100644 templates/apps/egui/gen/bin/desktop.rs.hbs create mode 100644 templates/apps/egui/src/lib.rs diff --git a/README.md b/README.md index 954e1ffd..08fbb93c 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,10 @@ cargo mobile init After some straightforward prompts, you'll be asked to select a template pack. Template packs are used to generate project boilerplate, i.e. using the `wry` template pack gives you a [wry](https://github.com/tauri-apps/wry) project that runs out-of-the-box on desktop and mobile. -| name | info | -| --------- | ------------------------------------- | -| wry | Minimal wry project | +| name | info | +| --------- | ----------------------------------------------------------------------------------------------------------------------| +| wry | Minimal wry project | +| egui | Full egui + winit + wgpu example based on [agdk-egui example](https://github.com/rust-mobile/rust-android-examples) | **Template pack contribution is welcomed** diff --git a/templates/apps/egui/.gitignore.hbs b/templates/apps/egui/.gitignore.hbs new file mode 100644 index 00000000..c3cb0ce4 --- /dev/null +++ b/templates/apps/egui/.gitignore.hbs @@ -0,0 +1,10 @@ +# Rust +target/ +**/*.rs.bk + +# cargo-mobile +.cargo/ +/gen + +# macOS +.DS_Store diff --git a/templates/apps/egui/Cargo.toml.hbs b/templates/apps/egui/Cargo.toml.hbs new file mode 100644 index 00000000..9c49ff9e --- /dev/null +++ b/templates/apps/egui/Cargo.toml.hbs @@ -0,0 +1,38 @@ +[package] +name = "{{app.name}}" +version = "0.1.0" +authors = ["{{author}}"] +edition = "2018" +resolver = "2" + +[lib] +crate-type = ["staticlib", "cdylib", "rlib"] + +[[bin]] +name = "{{app.name}}-desktop" +path = "gen/bin/desktop.rs" + +[package.metadata.cargo-android] +app-dependencies = [ + "com.google.android.material:material:1.8.0", +] +project-dependencies = [ "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21" ] +app-plugins = [ "org.jetbrains.kotlin.android" ] +app-theme-parent = "Theme.MaterialComponents.DayNight.DarkActionBar" + +[dependencies] +log = "0.4.14" +chrono = "0.4" +pollster = "0.2" +egui = "0.22" +wgpu = "0.16" +winit = { version = "0.28", features = ["android-native-activity"] } +egui_demo_lib = "0.22" +egui-winit = { version = "0.22", default-features = false } +egui-wgpu = { version = "0.22", features = [ "winit" ] } + +[target.'cfg(target_os = "android")'.dependencies] +android_logger = "0.13.1" + +[target.'cfg(not(target_os = "android"))'.dependencies] +env_logger = "0.9" diff --git a/templates/apps/egui/README.md b/templates/apps/egui/README.md new file mode 100644 index 00000000..055b886d --- /dev/null +++ b/templates/apps/egui/README.md @@ -0,0 +1,5 @@ +# egui + +This is an example based on [agdk-egui example](https://github.com/rust-mobile/rust-android-examples), using `egui`, `winit` and `wgpu` to run [egui_demo_app](https://github.com/emilk/egui/tree/master/egui_demo_app). + +To run this on desktop, just do `cargo run` like normal! For mobile, use `cargo android run` and `cargo apple run` respectively (or use `cargo android open` and `cargo apple open` to open in Android Studio and Xcode respectively). diff --git a/templates/apps/egui/gen/bin/desktop.rs.hbs b/templates/apps/egui/gen/bin/desktop.rs.hbs new file mode 100644 index 00000000..df976373 --- /dev/null +++ b/templates/apps/egui/gen/bin/desktop.rs.hbs @@ -0,0 +1,4 @@ +fn main() { + #[cfg(not(any(target_os = "android", target_os = "ios")))] + {{snake-case app.name}}::start_app(); +} diff --git a/templates/apps/egui/src/lib.rs b/templates/apps/egui/src/lib.rs new file mode 100644 index 00000000..22bdbd01 --- /dev/null +++ b/templates/apps/egui/src/lib.rs @@ -0,0 +1,170 @@ +use winit::event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget}; + +#[cfg(target_os = "android")] +use winit::platform::android::activity::AndroidApp; + +use winit::event_loop::ControlFlow; + +use egui_wgpu::winit::Painter; +use egui_winit::State; +//use egui_winit_platform::{Platform, PlatformDescriptor}; +use winit::event::Event::*; +const INITIAL_WIDTH: u32 = 1920; +const INITIAL_HEIGHT: u32 = 1080; + +/// A custom event type for the winit app. +enum Event { + RequestRedraw, +} + +/// Enable egui to request redraws via a custom Winit event... +#[derive(Clone)] +struct RepaintSignal(std::sync::Arc>>); + +fn create_window( + event_loop: &EventLoopWindowTarget, + state: &mut State, + painter: &mut Painter, +) -> winit::window::Window { + let window = winit::window::WindowBuilder::new() + .with_decorations(true) + .with_resizable(true) + .with_transparent(false) + .with_title("egui winit + wgpu example") + .with_inner_size(winit::dpi::PhysicalSize { + width: INITIAL_WIDTH, + height: INITIAL_HEIGHT, + }) + .build(event_loop) + .unwrap(); + + pollster::block_on(painter.set_window(Some(&window))).unwrap(); + + // NB: calling set_window will lazily initialize render state which + // means we will be able to query the maximum supported texture + // dimensions + if let Some(max_size) = painter.max_texture_side() { + state.set_max_texture_side(max_size); + } + + let pixels_per_point = window.scale_factor() as f32; + state.set_pixels_per_point(pixels_per_point); + + window.request_redraw(); + + window +} + +fn _main(event_loop: EventLoop) { + let ctx = egui::Context::default(); + let repaint_signal = RepaintSignal(std::sync::Arc::new(std::sync::Mutex::new( + event_loop.create_proxy(), + ))); + ctx.set_request_repaint_callback(move |_| { + repaint_signal + .0 + .lock() + .unwrap() + .send_event(Event::RequestRedraw) + .ok(); + }); + + let mut state = State::new(&event_loop); + let mut painter = Painter::new( + egui_wgpu::WgpuConfiguration::default(), + 1, // msaa samples + None, // depth bits + false, + ); + let mut window: Option = None; + let mut egui_demo_windows = egui_demo_lib::DemoWindows::default(); + + event_loop.run(move |event, event_loop, control_flow| match event { + Resumed => match window { + None => { + window = Some(create_window(event_loop, &mut state, &mut painter)); + } + Some(ref window) => { + pollster::block_on(painter.set_window(Some(window))).unwrap(); + window.request_redraw(); + } + }, + Suspended => { + window = None; + } + RedrawRequested(..) => { + if let Some(window) = window.as_ref() { + let raw_input = state.take_egui_input(window); + + let full_output = ctx.run(raw_input, |ctx| { + egui_demo_windows.ui(ctx); + }); + state.handle_platform_output(window, &ctx, full_output.platform_output); + + painter.paint_and_update_textures( + state.pixels_per_point(), + egui::Rgba::default().to_array(), + &ctx.tessellate(full_output.shapes), + &full_output.textures_delta, + false, + ); + + if full_output.repaint_after.is_zero() { + window.request_redraw(); + } + } + } + MainEventsCleared | UserEvent(Event::RequestRedraw) => { + if let Some(window) = window.as_ref() { + window.request_redraw(); + } + } + WindowEvent { event, .. } => { + match event { + winit::event::WindowEvent::Resized(size) => { + painter.on_window_resized(size.width, size.height); + } + winit::event::WindowEvent::CloseRequested => { + *control_flow = ControlFlow::Exit; + } + _ => {} + } + + let response = state.on_event(&ctx, &event); + if response.repaint { + if let Some(window) = window.as_ref() { + window.request_redraw(); + } + } + } + _ => (), + }); +} + +#[allow(dead_code)] +#[cfg(target_os = "android")] +#[no_mangle] +fn android_main(app: AndroidApp) { + use winit::platform::android::EventLoopBuilderExtAndroid; + + android_logger::init_once( + android_logger::Config::default().with_max_level(log::LevelFilter::Warn), + ); + + let event_loop = EventLoopBuilder::with_user_event() + .with_android_app(app) + .build(); + _main(event_loop); +} + +#[allow(dead_code)] +#[cfg(not(target_os = "android"))] +fn main() { + env_logger::builder() + .filter_level(log::LevelFilter::Warn) // Default Log Level + .parse_default_env() + .init(); + + let event_loop = EventLoopBuilder::with_user_event().build(); + _main(event_loop); +} diff --git a/templates/platforms/android-studio/app/src/main/res/values/styles.xml.hbs b/templates/platforms/android-studio/app/src/main/res/values/styles.xml.hbs index 5af3348a..a7d298ef 100644 --- a/templates/platforms/android-studio/app/src/main/res/values/styles.xml.hbs +++ b/templates/platforms/android-studio/app/src/main/res/values/styles.xml.hbs @@ -2,6 +2,7 @@ \ No newline at end of file From 412ae6e7f2954c06da12a15f194570503cf27039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Thu, 25 May 2023 15:14:22 +0200 Subject: [PATCH 2/6] make the egui example work on desktop --- templates/apps/egui/gen/bin/desktop.rs.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/apps/egui/gen/bin/desktop.rs.hbs b/templates/apps/egui/gen/bin/desktop.rs.hbs index df976373..a054a346 100644 --- a/templates/apps/egui/gen/bin/desktop.rs.hbs +++ b/templates/apps/egui/gen/bin/desktop.rs.hbs @@ -1,4 +1,4 @@ fn main() { #[cfg(not(any(target_os = "android", target_os = "ios")))] - {{snake-case app.name}}::start_app(); + {{snake-case app.name}}::main(); } From a086887f64253cf2f5542ab9a1fce9b27dd988f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Fri, 26 May 2023 21:20:40 +0200 Subject: [PATCH 3/6] remove wrong/unnecessary/out of place comments in the example --- templates/apps/egui/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/apps/egui/src/lib.rs b/templates/apps/egui/src/lib.rs index 22bdbd01..9efa7798 100644 --- a/templates/apps/egui/src/lib.rs +++ b/templates/apps/egui/src/lib.rs @@ -7,7 +7,7 @@ use winit::event_loop::ControlFlow; use egui_wgpu::winit::Painter; use egui_winit::State; -//use egui_winit_platform::{Platform, PlatformDescriptor}; + use winit::event::Event::*; const INITIAL_WIDTH: u32 = 1920; const INITIAL_HEIGHT: u32 = 1080; @@ -72,8 +72,8 @@ fn _main(event_loop: EventLoop) { let mut state = State::new(&event_loop); let mut painter = Painter::new( egui_wgpu::WgpuConfiguration::default(), - 1, // msaa samples - None, // depth bits + 1, // msaa samples + None, false, ); let mut window: Option = None; @@ -161,7 +161,7 @@ fn android_main(app: AndroidApp) { #[cfg(not(target_os = "android"))] fn main() { env_logger::builder() - .filter_level(log::LevelFilter::Warn) // Default Log Level + .filter_level(log::LevelFilter::Warn) .parse_default_env() .init(); From cbe21613ecc14f5da9a3de58efbb8eddf9b9b6e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Fri, 26 May 2023 21:23:43 +0200 Subject: [PATCH 4/6] properly group imports in the egui example --- templates/apps/egui/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/templates/apps/egui/src/lib.rs b/templates/apps/egui/src/lib.rs index 9efa7798..9c0e1c9d 100644 --- a/templates/apps/egui/src/lib.rs +++ b/templates/apps/egui/src/lib.rs @@ -1,14 +1,12 @@ -use winit::event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget}; - #[cfg(target_os = "android")] use winit::platform::android::activity::AndroidApp; -use winit::event_loop::ControlFlow; +use winit::event::Event::*; +use winit::event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopWindowTarget}; use egui_wgpu::winit::Painter; use egui_winit::State; -use winit::event::Event::*; const INITIAL_WIDTH: u32 = 1920; const INITIAL_HEIGHT: u32 = 1080; From 024bcc46ed65c0482f2b0cde8570b19a57c0e719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Fri, 26 May 2023 21:40:37 +0200 Subject: [PATCH 5/6] sign an empty commit From c06f5aff368a6bbe10dc5eb8dd9ced55d8f4a666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Fri, 26 May 2023 21:42:12 +0200 Subject: [PATCH 6/6] sign an empty commit