[app] Add demo app slider to change scale of all of Egui
This commit is contained in:
parent
251cde60f0
commit
a4e19d7207
9 changed files with 149 additions and 85 deletions
|
@ -5,6 +5,7 @@
|
||||||
* `ui.horizontal(...)` etc returns `Response`
|
* `ui.horizontal(...)` etc returns `Response`
|
||||||
* Add ability to override text color with `visuals.override_text_color`
|
* Add ability to override text color with `visuals.override_text_color`
|
||||||
* Refactored the interface for `egui::app::App`
|
* Refactored the interface for `egui::app::App`
|
||||||
|
* Demo App: Add slider to scale all of Egui
|
||||||
|
|
||||||
## 0.2.0 - 2020-10-10
|
## 0.2.0 - 2020-10-10
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,14 @@ pub trait App {
|
||||||
fn on_exit(&mut self, _storage: &mut dyn Storage) {}
|
fn on_exit(&mut self, _storage: &mut dyn Storage) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct WebInfo {
|
pub struct WebInfo {
|
||||||
/// e.g. "#fragment" part of "www.example.com/index.html#fragment"
|
/// e.g. "#fragment" part of "www.example.com/index.html#fragment"
|
||||||
pub web_location_hash: String,
|
pub web_location_hash: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about the backend passed to the use app each frame.
|
/// Information about the backend passed to the use app each frame.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct BackendInfo {
|
pub struct BackendInfo {
|
||||||
/// If the app is running in a Web context, this returns information about the environment.
|
/// If the app is running in a Web context, this returns information about the environment.
|
||||||
pub web_info: Option<WebInfo>,
|
pub web_info: Option<WebInfo>,
|
||||||
|
@ -41,14 +43,20 @@ pub struct BackendInfo {
|
||||||
/// Local time. Used for the clock in the demo app.
|
/// Local time. Used for the clock in the demo app.
|
||||||
/// Set to `None` if you don't know.
|
/// Set to `None` if you don't know.
|
||||||
pub seconds_since_midnight: Option<f64>,
|
pub seconds_since_midnight: Option<f64>,
|
||||||
|
|
||||||
|
/// The OS native pixels-per-point
|
||||||
|
pub native_pixels_per_point: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Action that can be taken by the user app.
|
/// Action that can be taken by the user app.
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
pub struct AppOutput {
|
pub struct AppOutput {
|
||||||
/// Set to `true` to stop the app.
|
/// Set to `true` to stop the app.
|
||||||
/// This does nothing for web apps.
|
/// This does nothing for web apps.
|
||||||
pub quit: bool,
|
pub quit: bool,
|
||||||
|
|
||||||
|
/// If the app sets this, change the `pixels_per_point` of Egui to this next frame.
|
||||||
|
pub pixels_per_point: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TextureAllocator {
|
pub trait TextureAllocator {
|
||||||
|
|
|
@ -188,6 +188,9 @@ pub struct DemoApp {
|
||||||
demo_window: DemoWindow,
|
demo_window: DemoWindow,
|
||||||
fractal_clock: FractalClock,
|
fractal_clock: FractalClock,
|
||||||
|
|
||||||
|
/// current slider value for current gui scale (backend demo only)
|
||||||
|
pixels_per_point: Option<f32>,
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "serde", serde(skip))]
|
||||||
frame_history: FrameHistory,
|
frame_history: FrameHistory,
|
||||||
|
|
||||||
|
@ -320,8 +323,6 @@ impl DemoApp {
|
||||||
|
|
||||||
let is_web = info.web_info.is_some();
|
let is_web = info.web_info.is_some();
|
||||||
|
|
||||||
let mut options = app::AppOutput::default();
|
|
||||||
|
|
||||||
if is_web {
|
if is_web {
|
||||||
ui.label("Egui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL.");
|
ui.label("Egui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL.");
|
||||||
ui.label(
|
ui.label(
|
||||||
|
@ -332,23 +333,17 @@ impl DemoApp {
|
||||||
ui.label("Project home page:");
|
ui.label("Project home page:");
|
||||||
ui.hyperlink("https://github.com/emilk/egui");
|
ui.hyperlink("https://github.com/emilk/egui");
|
||||||
});
|
});
|
||||||
} else {
|
ui.separator();
|
||||||
ui.heading("Egui");
|
|
||||||
options.quit |= ui.button("Quit").clicked;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
self.run_mode_ui(ui);
|
self.run_mode_ui(ui);
|
||||||
|
|
||||||
if self.run_mode == RunMode::Continuous {
|
ui.separator();
|
||||||
ui.label(format!(
|
|
||||||
"Repainting the UI each frame. FPS: {:.1}",
|
let mut output = app::AppOutput::default();
|
||||||
self.frame_history.fps()
|
output.pixels_per_point = self.pixels_per_point_ui(ui, info);
|
||||||
));
|
|
||||||
} else {
|
ui.separator();
|
||||||
ui.label("Only running UI code when there are animations or input");
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
self.frame_history.ui(ui);
|
self.frame_history.ui(ui);
|
||||||
|
@ -359,7 +354,41 @@ impl DemoApp {
|
||||||
"Show color blend test (debug backend painter)",
|
"Show color blend test (debug backend painter)",
|
||||||
);
|
);
|
||||||
|
|
||||||
options
|
if !is_web {
|
||||||
|
output.quit |= ui.button("Quit").clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pixels_per_point_ui(&mut self, ui: &mut Ui, info: &app::BackendInfo) -> Option<f32> {
|
||||||
|
self.pixels_per_point = self
|
||||||
|
.pixels_per_point
|
||||||
|
.or(info.native_pixels_per_point)
|
||||||
|
.or_else(|| Some(ui.ctx().pixels_per_point()));
|
||||||
|
if let Some(pixels_per_point) = &mut self.pixels_per_point {
|
||||||
|
ui.add(
|
||||||
|
Slider::f32(pixels_per_point, 0.5..=5.0)
|
||||||
|
.logarithmic(true)
|
||||||
|
.text("Scale (physical pixels per point)"),
|
||||||
|
);
|
||||||
|
if let Some(native_pixels_per_point) = info.native_pixels_per_point {
|
||||||
|
if ui
|
||||||
|
.button(format!(
|
||||||
|
"Reset scale to native value ({:.1})",
|
||||||
|
native_pixels_per_point
|
||||||
|
))
|
||||||
|
.clicked
|
||||||
|
{
|
||||||
|
*pixels_per_point = native_pixels_per_point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ui.ctx().is_using_mouse() {
|
||||||
|
// We wait until mouse release to activate:
|
||||||
|
return Some(*pixels_per_point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_mode_ui(&mut self, ui: &mut Ui) {
|
fn run_mode_ui(&mut self, ui: &mut Ui) {
|
||||||
|
@ -371,6 +400,15 @@ impl DemoApp {
|
||||||
ui.radio_value(run_mode, RunMode::Reactive, "Reactive")
|
ui.radio_value(run_mode, RunMode::Reactive, "Reactive")
|
||||||
.on_hover_text("Repaint when there are animations or input (e.g. mouse movement)");
|
.on_hover_text("Repaint when there are animations or input (e.g. mouse movement)");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if self.run_mode == RunMode::Continuous {
|
||||||
|
ui.label(format!(
|
||||||
|
"Repainting the UI each frame. FPS: {:.1}",
|
||||||
|
self.frame_history.fps()
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
ui.label("Only running UI code when there are animations or input");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -388,7 +388,7 @@ impl InputState {
|
||||||
ui.label(format!("scroll_delta: {:?} points", scroll_delta));
|
ui.label(format!("scroll_delta: {:?} points", scroll_delta));
|
||||||
ui.label(format!("screen_size: {:?} points", screen_size));
|
ui.label(format!("screen_size: {:?} points", screen_size));
|
||||||
ui.label(format!(
|
ui.label(format!(
|
||||||
"{:?} points for each physical pixel (HDPI factor)",
|
"{:?} physical pixels for each logical point",
|
||||||
pixels_per_point
|
pixels_per_point
|
||||||
));
|
));
|
||||||
ui.label(format!("time: {:.3} s", time));
|
ui.label(format!("time: {:.3} s", time));
|
||||||
|
|
|
@ -51,7 +51,10 @@ pub fn run(title: &str, mut storage: FileStorage, mut app: impl App + 'static) -
|
||||||
let mut ctx = egui::Context::new();
|
let mut ctx = egui::Context::new();
|
||||||
*ctx.memory() = egui::app::get_value(&storage, EGUI_MEMORY_KEY).unwrap_or_default();
|
*ctx.memory() = egui::app::get_value(&storage, EGUI_MEMORY_KEY).unwrap_or_default();
|
||||||
|
|
||||||
let mut raw_input = make_raw_input(&display);
|
let mut raw_input = egui::RawInput {
|
||||||
|
pixels_per_point: Some(native_pixels_per_point(&display)),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let mut previous_frame_time = None;
|
let mut previous_frame_time = None;
|
||||||
|
@ -62,11 +65,14 @@ pub fn run(title: &str, mut storage: FileStorage, mut app: impl App + 'static) -
|
||||||
let mut redraw = || {
|
let mut redraw = || {
|
||||||
let egui_start = Instant::now();
|
let egui_start = Instant::now();
|
||||||
raw_input.time = start_time.elapsed().as_nanos() as f64 * 1e-9;
|
raw_input.time = start_time.elapsed().as_nanos() as f64 * 1e-9;
|
||||||
|
raw_input.screen_size =
|
||||||
|
screen_size_in_pixels(&display) / raw_input.pixels_per_point.unwrap();
|
||||||
|
|
||||||
let backend_info = egui::app::BackendInfo {
|
let backend_info = egui::app::BackendInfo {
|
||||||
web_info: None,
|
web_info: None,
|
||||||
cpu_usage: previous_frame_time,
|
cpu_usage: previous_frame_time,
|
||||||
seconds_since_midnight: Some(seconds_since_midnight()),
|
seconds_since_midnight: Some(seconds_since_midnight()),
|
||||||
|
native_pixels_per_point: Some(native_pixels_per_point(&display)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut ui = ctx.begin_frame(raw_input.take());
|
let mut ui = ctx.begin_frame(raw_input.take());
|
||||||
|
@ -75,10 +81,17 @@ pub fn run(title: &str, mut storage: FileStorage, mut app: impl App + 'static) -
|
||||||
|
|
||||||
let frame_time = (Instant::now() - egui_start).as_secs_f64() as f32;
|
let frame_time = (Instant::now() - egui_start).as_secs_f64() as f32;
|
||||||
previous_frame_time = Some(frame_time);
|
previous_frame_time = Some(frame_time);
|
||||||
painter.paint_jobs(&display, paint_jobs, &ctx.texture());
|
painter.paint_jobs(&display, ctx.pixels_per_point(), paint_jobs, &ctx.texture());
|
||||||
|
|
||||||
{
|
{
|
||||||
let egui::app::AppOutput { quit } = app_output;
|
let egui::app::AppOutput {
|
||||||
|
quit,
|
||||||
|
pixels_per_point,
|
||||||
|
} = app_output;
|
||||||
|
if let Some(pixels_per_point) = pixels_per_point {
|
||||||
|
// User changed GUI scale
|
||||||
|
raw_input.pixels_per_point = Some(pixels_per_point);
|
||||||
|
}
|
||||||
|
|
||||||
*control_flow = if quit {
|
*control_flow = if quit {
|
||||||
glutin::event_loop::ControlFlow::Exit
|
glutin::event_loop::ControlFlow::Exit
|
||||||
|
|
|
@ -27,30 +27,16 @@ pub fn input_to_egui(
|
||||||
use glutin::event::WindowEvent::*;
|
use glutin::event::WindowEvent::*;
|
||||||
match event {
|
match event {
|
||||||
CloseRequested | Destroyed => *control_flow = ControlFlow::Exit,
|
CloseRequested | Destroyed => *control_flow = ControlFlow::Exit,
|
||||||
|
|
||||||
Resized(physical_size) => {
|
|
||||||
raw_input.screen_size =
|
|
||||||
egui::vec2(physical_size.width as f32, physical_size.height as f32)
|
|
||||||
/ raw_input.pixels_per_point.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
ScaleFactorChanged {
|
|
||||||
scale_factor,
|
|
||||||
new_inner_size,
|
|
||||||
} => {
|
|
||||||
raw_input.pixels_per_point = Some(scale_factor as f32);
|
|
||||||
raw_input.screen_size =
|
|
||||||
egui::vec2(new_inner_size.width as f32, new_inner_size.height as f32)
|
|
||||||
/ (scale_factor as f32);
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseInput { state, .. } => {
|
MouseInput { state, .. } => {
|
||||||
raw_input.mouse_down = state == glutin::event::ElementState::Pressed;
|
raw_input.mouse_down = state == glutin::event::ElementState::Pressed;
|
||||||
}
|
}
|
||||||
CursorMoved { position, .. } => {
|
CursorMoved {
|
||||||
|
position: pos_in_pixels,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
raw_input.mouse_pos = Some(pos2(
|
raw_input.mouse_pos = Some(pos2(
|
||||||
position.x as f32 / raw_input.pixels_per_point.unwrap(),
|
pos_in_pixels.x as f32 / raw_input.pixels_per_point.unwrap(),
|
||||||
position.y as f32 / raw_input.pixels_per_point.unwrap(),
|
pos_in_pixels.y as f32 / raw_input.pixels_per_point.unwrap(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
CursorLeft { .. } => {
|
CursorLeft { .. } => {
|
||||||
|
@ -213,14 +199,11 @@ pub fn seconds_since_midnight() -> f64 {
|
||||||
time.num_seconds_from_midnight() as f64 + 1e-9 * (time.nanosecond() as f64)
|
time.num_seconds_from_midnight() as f64 + 1e-9 * (time.nanosecond() as f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_raw_input(display: &glium::Display) -> egui::RawInput {
|
pub fn screen_size_in_pixels(display: &glium::Display) -> Vec2 {
|
||||||
let pixels_per_point = display.gl_window().window().scale_factor() as f32;
|
let (width_in_pixels, height_in_pixels) = display.get_framebuffer_dimensions();
|
||||||
egui::RawInput {
|
vec2(width_in_pixels as f32, height_in_pixels as f32)
|
||||||
screen_size: {
|
}
|
||||||
let (width, height) = display.get_framebuffer_dimensions();
|
|
||||||
vec2(width as f32, height as f32) / pixels_per_point
|
pub fn native_pixels_per_point(display: &glium::Display) -> f32 {
|
||||||
},
|
display.gl_window().window().scale_factor() as f32
|
||||||
pixels_per_point: Some(pixels_per_point),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,16 +152,23 @@ impl Painter {
|
||||||
pub fn paint_jobs(
|
pub fn paint_jobs(
|
||||||
&mut self,
|
&mut self,
|
||||||
display: &glium::Display,
|
display: &glium::Display,
|
||||||
|
pixels_per_point: f32,
|
||||||
jobs: PaintJobs,
|
jobs: PaintJobs,
|
||||||
texture: &egui::Texture,
|
egui_texture: &egui::Texture,
|
||||||
) {
|
) {
|
||||||
self.upload_egui_texture(display, texture);
|
self.upload_egui_texture(display, egui_texture);
|
||||||
self.upload_pending_user_textures(display);
|
self.upload_pending_user_textures(display);
|
||||||
|
|
||||||
let mut target = display.draw();
|
let mut target = display.draw();
|
||||||
target.clear_color(0.0, 0.0, 0.0, 0.0);
|
target.clear_color(0.0, 0.0, 0.0, 0.0);
|
||||||
for (clip_rect, triangles) in jobs {
|
for (clip_rect, triangles) in jobs {
|
||||||
self.paint_job(&mut target, display, clip_rect, &triangles)
|
self.paint_job(
|
||||||
|
&mut target,
|
||||||
|
display,
|
||||||
|
pixels_per_point,
|
||||||
|
clip_rect,
|
||||||
|
&triangles,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
target.finish().unwrap();
|
target.finish().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -183,6 +190,7 @@ impl Painter {
|
||||||
&mut self,
|
&mut self,
|
||||||
target: &mut Frame,
|
target: &mut Frame,
|
||||||
display: &glium::Display,
|
display: &glium::Display,
|
||||||
|
pixels_per_point: f32,
|
||||||
clip_rect: Rect,
|
clip_rect: Rect,
|
||||||
triangles: &Triangles,
|
triangles: &Triangles,
|
||||||
) {
|
) {
|
||||||
|
@ -217,15 +225,14 @@ impl Painter {
|
||||||
let index_buffer =
|
let index_buffer =
|
||||||
glium::IndexBuffer::new(display, PrimitiveType::TrianglesList, &indices).unwrap();
|
glium::IndexBuffer::new(display, PrimitiveType::TrianglesList, &indices).unwrap();
|
||||||
|
|
||||||
let pixels_per_point = display.gl_window().window().scale_factor() as f32;
|
let (width_in_pixels, height_in_pixels) = display.get_framebuffer_dimensions();
|
||||||
let (width_pixels, height_pixels) = display.get_framebuffer_dimensions();
|
let width_in_points = width_in_pixels as f32 / pixels_per_point;
|
||||||
let width_points = width_pixels as f32 / pixels_per_point;
|
let height_in_points = height_in_pixels as f32 / pixels_per_point;
|
||||||
let height_points = height_pixels as f32 / pixels_per_point;
|
|
||||||
|
|
||||||
let texture = self.get_texture(triangles.texture_id);
|
let texture = self.get_texture(triangles.texture_id);
|
||||||
|
|
||||||
let uniforms = uniform! {
|
let uniforms = uniform! {
|
||||||
u_screen_size: [width_points, height_points],
|
u_screen_size: [width_in_points, height_in_points],
|
||||||
u_sampler: texture.sampled().wrap_function(SamplerWrapFunction::Clamp),
|
u_sampler: texture.sampled().wrap_function(SamplerWrapFunction::Clamp),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,10 +262,10 @@ impl Painter {
|
||||||
let clip_max_y = pixels_per_point * clip_rect.max.y;
|
let clip_max_y = pixels_per_point * clip_rect.max.y;
|
||||||
|
|
||||||
// Make sure clip rect can fit withing an `u32`:
|
// Make sure clip rect can fit withing an `u32`:
|
||||||
let clip_min_x = clamp(clip_min_x, 0.0..=width_pixels as f32);
|
let clip_min_x = clamp(clip_min_x, 0.0..=width_in_pixels as f32);
|
||||||
let clip_min_y = clamp(clip_min_y, 0.0..=height_pixels as f32);
|
let clip_min_y = clamp(clip_min_y, 0.0..=height_in_pixels as f32);
|
||||||
let clip_max_x = clamp(clip_max_x, clip_min_x..=width_pixels as f32);
|
let clip_max_x = clamp(clip_max_x, clip_min_x..=width_in_pixels as f32);
|
||||||
let clip_max_y = clamp(clip_max_y, clip_min_y..=height_pixels as f32);
|
let clip_max_y = clamp(clip_max_y, clip_min_y..=height_in_pixels as f32);
|
||||||
|
|
||||||
let clip_min_x = clip_min_x.round() as u32;
|
let clip_min_x = clip_min_x.round() as u32;
|
||||||
let clip_min_y = clip_min_y.round() as u32;
|
let clip_min_y = clip_min_y.round() as u32;
|
||||||
|
@ -269,7 +276,7 @@ impl Painter {
|
||||||
blend,
|
blend,
|
||||||
scissor: Some(glium::Rect {
|
scissor: Some(glium::Rect {
|
||||||
left: clip_min_x,
|
left: clip_min_x,
|
||||||
bottom: height_pixels - clip_max_y,
|
bottom: height_in_pixels - clip_max_y,
|
||||||
width: clip_max_x - clip_min_x,
|
width: clip_max_x - clip_min_x,
|
||||||
height: clip_max_y - clip_min_y,
|
height: clip_max_y - clip_min_y,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::*;
|
||||||
|
|
||||||
pub use egui::{
|
pub use egui::{
|
||||||
app::{App, WebInfo},
|
app::{App, WebInfo},
|
||||||
Srgba,
|
pos2, Srgba,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -105,13 +105,17 @@ pub struct WebInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebInput {
|
impl WebInput {
|
||||||
pub fn new_frame(&mut self) -> egui::RawInput {
|
pub fn new_frame(&mut self, pixels_per_point: f32) -> egui::RawInput {
|
||||||
|
// Compensate for potential different scale of Egui compared to native.
|
||||||
|
let scale = native_pixels_per_point() / pixels_per_point;
|
||||||
|
let scroll_delta = std::mem::take(&mut self.scroll_delta) * scale;
|
||||||
|
let mouse_pos = self.mouse_pos.map(|mp| pos2(mp.x * scale, mp.y * scale));
|
||||||
egui::RawInput {
|
egui::RawInput {
|
||||||
mouse_down: self.mouse_down,
|
mouse_down: self.mouse_down,
|
||||||
mouse_pos: self.mouse_pos,
|
mouse_pos,
|
||||||
scroll_delta: std::mem::take(&mut self.scroll_delta),
|
scroll_delta,
|
||||||
screen_size: screen_size().unwrap(),
|
screen_size: screen_size_in_native_points().unwrap() * scale,
|
||||||
pixels_per_point: Some(pixels_per_point()),
|
pixels_per_point: Some(pixels_per_point),
|
||||||
time: now_sec(),
|
time: now_sec(),
|
||||||
events: std::mem::take(&mut self.events),
|
events: std::mem::take(&mut self.events),
|
||||||
}
|
}
|
||||||
|
@ -121,6 +125,7 @@ impl WebInput {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
pub struct AppRunner {
|
pub struct AppRunner {
|
||||||
|
pixels_per_point: f32,
|
||||||
pub web_backend: WebBackend,
|
pub web_backend: WebBackend,
|
||||||
pub web_input: WebInput,
|
pub web_input: WebInput,
|
||||||
pub app: Box<dyn App>,
|
pub app: Box<dyn App>,
|
||||||
|
@ -130,6 +135,7 @@ pub struct AppRunner {
|
||||||
impl AppRunner {
|
impl AppRunner {
|
||||||
pub fn new(web_backend: WebBackend, app: Box<dyn App>) -> Result<Self, JsValue> {
|
pub fn new(web_backend: WebBackend, app: Box<dyn App>) -> Result<Self, JsValue> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
pixels_per_point: native_pixels_per_point(),
|
||||||
web_backend,
|
web_backend,
|
||||||
web_input: Default::default(),
|
web_input: Default::default(),
|
||||||
app,
|
app,
|
||||||
|
@ -142,9 +148,9 @@ impl AppRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logic(&mut self) -> Result<(egui::Output, egui::PaintJobs), JsValue> {
|
pub fn logic(&mut self) -> Result<(egui::Output, egui::PaintJobs), JsValue> {
|
||||||
resize_to_screen_size(self.web_backend.canvas_id());
|
resize_canvas_to_screen_size(self.web_backend.canvas_id());
|
||||||
|
|
||||||
let raw_input = self.web_input.new_frame();
|
let raw_input = self.web_input.new_frame(self.pixels_per_point);
|
||||||
|
|
||||||
let backend_info = egui::app::BackendInfo {
|
let backend_info = egui::app::BackendInfo {
|
||||||
web_info: Some(WebInfo {
|
web_info: Some(WebInfo {
|
||||||
|
@ -152,6 +158,7 @@ impl AppRunner {
|
||||||
}),
|
}),
|
||||||
cpu_usage: self.web_backend.previous_frame_time,
|
cpu_usage: self.web_backend.previous_frame_time,
|
||||||
seconds_since_midnight: Some(seconds_since_midnight()),
|
seconds_since_midnight: Some(seconds_since_midnight()),
|
||||||
|
native_pixels_per_point: Some(native_pixels_per_point()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut ui = self.web_backend.begin_frame(raw_input);
|
let mut ui = self.web_backend.begin_frame(raw_input);
|
||||||
|
@ -162,7 +169,14 @@ impl AppRunner {
|
||||||
handle_output(&egui_output);
|
handle_output(&egui_output);
|
||||||
|
|
||||||
{
|
{
|
||||||
let egui::app::AppOutput { quit: _ } = app_output;
|
let egui::app::AppOutput {
|
||||||
|
quit: _,
|
||||||
|
pixels_per_point,
|
||||||
|
} = app_output;
|
||||||
|
|
||||||
|
if let Some(pixels_per_point) = pixels_per_point {
|
||||||
|
self.pixels_per_point = pixels_per_point;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((egui_output, paint_jobs))
|
Ok((egui_output, paint_jobs))
|
||||||
|
|
|
@ -17,14 +17,6 @@ pub fn console_log(s: String) {
|
||||||
web_sys::console::log_1(&s.into());
|
web_sys::console::log_1(&s.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn screen_size() -> Option<egui::Vec2> {
|
|
||||||
let window = web_sys::window()?;
|
|
||||||
Some(egui::Vec2::new(
|
|
||||||
window.inner_width().ok()?.as_f64()? as f32,
|
|
||||||
window.inner_height().ok()?.as_f64()? as f32,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn now_sec() -> f64 {
|
pub fn now_sec() -> f64 {
|
||||||
web_sys::window()
|
web_sys::window()
|
||||||
.expect("should have a Window")
|
.expect("should have a Window")
|
||||||
|
@ -40,7 +32,15 @@ pub fn seconds_since_midnight() -> f64 {
|
||||||
seconds as f64 + 1e-3 * (d.get_milliseconds() as f64)
|
seconds as f64 + 1e-3 * (d.get_milliseconds() as f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pixels_per_point() -> f32 {
|
pub fn screen_size_in_native_points() -> Option<egui::Vec2> {
|
||||||
|
let window = web_sys::window()?;
|
||||||
|
Some(egui::Vec2::new(
|
||||||
|
window.inner_width().ok()?.as_f64()? as f32,
|
||||||
|
window.inner_height().ok()?.as_f64()? as f32,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn native_pixels_per_point() -> f32 {
|
||||||
let pixels_per_point = web_sys::window().unwrap().device_pixel_ratio() as f32;
|
let pixels_per_point = web_sys::window().unwrap().device_pixel_ratio() as f32;
|
||||||
if pixels_per_point > 0.0 && pixels_per_point.is_finite() {
|
if pixels_per_point > 0.0 && pixels_per_point.is_finite() {
|
||||||
pixels_per_point
|
pixels_per_point
|
||||||
|
@ -78,11 +78,11 @@ pub fn pos_from_touch_event(event: &web_sys::TouchEvent) -> egui::Pos2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize_to_screen_size(canvas_id: &str) -> Option<()> {
|
pub fn resize_canvas_to_screen_size(canvas_id: &str) -> Option<()> {
|
||||||
let canvas = canvas_element(canvas_id)?;
|
let canvas = canvas_element(canvas_id)?;
|
||||||
|
|
||||||
let screen_size = screen_size()?;
|
let screen_size = screen_size_in_native_points()?;
|
||||||
let pixels_per_point = pixels_per_point();
|
let pixels_per_point = native_pixels_per_point();
|
||||||
canvas
|
canvas
|
||||||
.style()
|
.style()
|
||||||
.set_property("width", &format!("{}px", screen_size.x))
|
.set_property("width", &format!("{}px", screen_size.x))
|
||||||
|
|
Loading…
Reference in a new issue