first commit

This commit is contained in:
Lucas Schumacher 2024-04-25 15:21:01 -04:00
commit 9911fa4571
18 changed files with 3672 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
target
.DS_Store
dist

3216
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

51
Cargo.toml Normal file
View File

@ -0,0 +1,51 @@
[package]
name = "eframe_template_android"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
# Common dependencies
[dependencies]
egui = "0.27.0"
log = "0.4.21"
# eframe features for non android targets
[target.'cfg(not(target_os = "android"))'.dependencies.eframe]
version = "0.27.0"
default-features = false
features = ["accesskit", "default_fonts", "glow"]
# eframe features for android targets
[target.'cfg(target_os = "android")'.dependencies.eframe]
version = "0.27.0"
default-features = false
features = ["accesskit", "default_fonts", "glow", "android-native-activity"]
# android only dependencies
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.13.3"
#android-activity = { version = "0.5", features = ["native-activity"] }
winit = { version = "0.29.4", features = ["android-native-activity"] }
# native only dependencies
[target.'cfg(all(not(target_arch = "wasm32"), not(target_os = "android")))'.dependencies]
env_logger = "0.10"
# web only dependencies
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen-futures = "0.4"
[profile.release]
opt-level = 2
# Optimize all dependencies even in debug builds:
[profile.dev.package."*"]
opt-level = 2
[lib]
crate-type = ["cdylib"]
[[bin]]
name = "eframe_template"
path = "src/main.rs"

23
LICENSE-MIT Normal file
View File

@ -0,0 +1,23 @@
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

0
README.md Normal file
View File

1
Trunk.toml Normal file
View File

@ -0,0 +1 @@
[build]

BIN
assets/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
assets/icon-1024.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

BIN
assets/icon-256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

28
assets/manifest.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "egui Template PWA",
"short_name": "egui-template-pwa",
"icons": [
{
"src": "./icon-256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "./maskable_icon_x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "./icon-1024.png",
"sizes": "1024x1024",
"type": "image/png"
}
],
"lang": "en-US",
"id": "/index.html",
"start_url": "./index.html",
"display": "standalone",
"background_color": "white",
"theme_color": "white"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

25
assets/sw.js Normal file
View File

@ -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);
})
);
});

140
index.html Normal file
View File

@ -0,0 +1,140 @@
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- Disable zooming: -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<head>
<!-- change this to your project name -->
<title>eframe template</title>
<!-- config for our rust wasm binary. go to https://trunkrs.dev/assets/#rust for more customization -->
<link data-trunk rel="rust" data-target-name="eframe-template" data-wasm-opt="2" />
<!-- this is the base url relative to which other urls will be constructed. trunk will insert this from the public-url option -->
<base data-trunk-public-url />
<link data-trunk rel="icon" href="assets/favicon.ico">
<link data-trunk rel="copy-file" href="assets/sw.js" />
<link data-trunk rel="copy-file" href="assets/manifest.json" />
<link data-trunk rel="copy-file" href="assets/icon-1024.png" />
<link data-trunk rel="copy-file" href="assets/icon-256.png" />
<link data-trunk rel="copy-file" href="assets/icon_ios_touch_192.png" />
<link data-trunk rel="copy-file" href="assets/maskable_icon_x512.png" />
<link rel="manifest" href="manifest.json">
<link rel="apple-touch-icon" href="icon_ios_touch_192.png">
<meta name="theme-color" media="(prefers-color-scheme: light)" content="white">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#404040">
<style>
html {
/* Remove touch delay: */
touch-action: manipulation;
}
body {
/* Light mode background color for what is not covered by the egui canvas,
or where the egui canvas is translucent. */
background: #909090;
}
@media (prefers-color-scheme: dark) {
body {
/* Dark mode background color for what is not covered by the egui canvas,
or where the egui canvas is translucent. */
background: #404040;
}
}
/* Allow canvas to fill entire web page: */
html,
body {
overflow: hidden;
margin: 0 !important;
padding: 0 !important;
height: 100%;
width: 100%;
}
/* Position canvas in center-top: */
canvas {
margin-right: auto;
margin-left: auto;
display: block;
position: absolute;
top: 0%;
left: 50%;
transform: translate(-50%, 0%);
}
.centered {
margin-right: auto;
margin-left: auto;
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #f0f0f0;
font-size: 24px;
font-family: Ubuntu-Light, Helvetica, sans-serif;
text-align: center;
}
/* ---------------------------------------------- */
/* Loading animation from https://loading.io/css/ */
.lds-dual-ring {
display: inline-block;
width: 24px;
height: 24px;
}
.lds-dual-ring:after {
content: " ";
display: block;
width: 24px;
height: 24px;
margin: 0px;
border-radius: 50%;
border: 3px solid #fff;
border-color: #fff transparent #fff transparent;
animation: lds-dual-ring 1.2s linear infinite;
}
@keyframes lds-dual-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<!-- The WASM code will resize the canvas dynamically -->
<!-- the id is hardcoded in main.rs . so, make sure both match. -->
<canvas id="the_canvas_id"></canvas>
<!--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 -->
<script>
// We disable caching during development so that we always view the latest version.
if ('serviceWorker' in navigator && window.location.hash !== "#dev") {
window.addEventListener('load', function () {
navigator.serviceWorker.register('sw.js');
});
}
</script>
</body>
</html>
<!-- Powered by egui: https://github.com/emilk/egui/ -->

10
rust-toolchain Normal file
View File

@ -0,0 +1,10 @@
# If you see this, run "rustup self update" to get rustup 1.23 or newer.
# NOTE: above comment is for older `rustup` (before TOML support was added),
# which will treat the first line as the toolchain name, and therefore show it
# to the user in the error, instead of "error: invalid channel name '[toolchain]'".
[toolchain]
channel = "1.76.0"
components = [ "rustfmt", "clippy" ]
targets = [ "wasm32-unknown-unknown" ]

101
src/app.rs Normal file
View File

@ -0,0 +1,101 @@
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
pub struct TemplateApp {
// Example stuff:
label: String,
value: f32,
}
impl Default for TemplateApp {
fn default() -> Self {
Self {
// Example stuff:
label: "Hello World!".to_owned(),
value: 2.7,
}
}
}
impl TemplateApp {
/// 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`.
// Load previous app state (if any).
// Note that you must enable the `persistence` feature for this to work.
Default::default()
}
}
impl eframe::App for TemplateApp {
/// Called by the frame work to save state before shutdown.
fn save(&mut self, _storage: &mut dyn eframe::Storage) {}
/// 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) {
// Put your widgets into a `SidePanel`, `TopBottomPanel`, `CentralPanel`, `Window` or `Area`.
// For inspiration and more examples, go to https://emilk.github.io/egui
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);
});
});
egui::CentralPanel::default().show(ctx, |ui| {
// The central panel the region left after adding TopPanel's and SidePanel's
ui.heading("eframe template");
ui.horizontal(|ui| {
ui.label("Write something: ");
ui.text_edit_singleline(&mut self.label);
});
ui.add(egui::Slider::new(&mut self.value, 0.0..=10.0).text("value"));
if ui.button("Increment").clicked() {
self.value += 1.0;
}
ui.separator();
ui.add(egui::github_link_file!(
"https://github.com/emilk/eframe_template/blob/main/",
"Source code."
));
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
powered_by_egui_and_eframe(ui);
egui::warn_if_debug_build(ui);
});
});
}
}
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",
);
ui.label(".");
});
}

27
src/lib.rs Normal file
View File

@ -0,0 +1,27 @@
#![warn(clippy::all, rust_2018_idioms)]
pub mod app;
pub use app::TemplateApp;
#[cfg(target_os = "android")]
#[no_mangle]
fn android_main(app: winit::platform::android::activity::AndroidApp) {
use winit::platform::android::EventLoopBuilderExtAndroid;
android_logger::init_once(
android_logger::Config::default().with_max_level(log::LevelFilter::Debug),
);
let mut options = eframe::NativeOptions::default();
options.event_loop_builder = Some(Box::new(move |builder| {
builder.with_android_app(app);
}));
let res = eframe::run_native(
"eframe template",
options,
Box::new(|cc| Box::new(app::TemplateApp::new(cc))),
);
if let Err(e) = res {
log::error!("{e:?}");
}
}

47
src/main.rs Normal file
View File

@ -0,0 +1,47 @@
mod app;
use app::TemplateApp;
//#[cfg(target_os = "android")]
//fn main() {}
// When compiling natively:
#[cfg(all(not(target_arch = "wasm32"), not(target_os = "android")))]
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([400.0, 300.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(
"eframe template",
native_options,
Box::new(|cc| Box::new(TemplateApp::new(cc))),
)
}
// 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 {
eframe::WebRunner::new()
.start(
"the_canvas_id", // hardcode it
web_options,
Box::new(|cc| Box::new(TemplateApp::new(cc))),
)
.await
.expect("failed to start eframe");
});
}