2021-01-02 10:59:20 +00:00
|
|
|
//! [`egui`] bindings for [`glium`](https://github.com/glium/glium).
|
|
|
|
//!
|
2021-04-25 15:02:27 +00:00
|
|
|
//! The main type you want to use is [`EguiGlium`].
|
2021-01-02 10:59:20 +00:00
|
|
|
//!
|
2021-04-25 15:02:27 +00:00
|
|
|
//! This library is an [`epi`] backend.
|
2021-01-02 10:59:20 +00:00
|
|
|
//! If you are writing an app, you may want to look at [`eframe`](https://docs.rs/eframe) instead.
|
|
|
|
|
2021-06-23 07:16:39 +00:00
|
|
|
// Forbid warnings in release builds:
|
|
|
|
#![cfg_attr(not(debug_assertions), deny(warnings))]
|
2021-04-15 08:35:15 +00:00
|
|
|
#![forbid(unsafe_code)]
|
2021-09-28 15:33:28 +00:00
|
|
|
#![warn(
|
|
|
|
clippy::all,
|
|
|
|
clippy::await_holding_lock,
|
|
|
|
clippy::char_lit_as_u8,
|
|
|
|
clippy::checked_conversions,
|
|
|
|
clippy::dbg_macro,
|
|
|
|
clippy::debug_assert_with_mut_call,
|
2021-10-20 14:30:39 +00:00
|
|
|
clippy::disallowed_method,
|
2021-09-28 15:33:28 +00:00
|
|
|
clippy::doc_markdown,
|
|
|
|
clippy::empty_enum,
|
|
|
|
clippy::enum_glob_use,
|
|
|
|
clippy::exit,
|
|
|
|
clippy::expl_impl_clone_on_copy,
|
|
|
|
clippy::explicit_deref_methods,
|
|
|
|
clippy::explicit_into_iter_loop,
|
|
|
|
clippy::fallible_impl_from,
|
|
|
|
clippy::filter_map_next,
|
2021-10-20 14:30:39 +00:00
|
|
|
clippy::flat_map_option,
|
2021-09-28 15:33:28 +00:00
|
|
|
clippy::float_cmp_const,
|
|
|
|
clippy::fn_params_excessive_bools,
|
2021-10-20 14:30:39 +00:00
|
|
|
clippy::from_iter_instead_of_collect,
|
2021-09-28 15:33:28 +00:00
|
|
|
clippy::if_let_mutex,
|
2021-10-20 14:30:39 +00:00
|
|
|
clippy::implicit_clone,
|
2021-09-28 15:33:28 +00:00
|
|
|
clippy::imprecise_flops,
|
|
|
|
clippy::inefficient_to_string,
|
|
|
|
clippy::invalid_upcast_comparisons,
|
2021-10-20 14:30:39 +00:00
|
|
|
clippy::large_digit_groups,
|
|
|
|
clippy::large_stack_arrays,
|
2021-09-28 15:33:28 +00:00
|
|
|
clippy::large_types_passed_by_value,
|
|
|
|
clippy::let_unit_value,
|
|
|
|
clippy::linkedlist,
|
|
|
|
clippy::lossy_float_literal,
|
|
|
|
clippy::macro_use_imports,
|
|
|
|
clippy::manual_ok_or,
|
|
|
|
clippy::map_err_ignore,
|
|
|
|
clippy::map_flatten,
|
2021-10-20 14:30:39 +00:00
|
|
|
clippy::map_unwrap_or,
|
2021-09-28 15:33:28 +00:00
|
|
|
clippy::match_on_vec_items,
|
|
|
|
clippy::match_same_arms,
|
2021-10-20 14:30:39 +00:00
|
|
|
clippy::match_wild_err_arm,
|
2021-09-28 15:33:28 +00:00
|
|
|
clippy::match_wildcard_for_single_variants,
|
|
|
|
clippy::mem_forget,
|
|
|
|
clippy::mismatched_target_os,
|
|
|
|
clippy::missing_errors_doc,
|
|
|
|
clippy::missing_safety_doc,
|
|
|
|
clippy::mut_mut,
|
|
|
|
clippy::mutex_integer,
|
|
|
|
clippy::needless_borrow,
|
|
|
|
clippy::needless_continue,
|
2021-10-20 14:30:39 +00:00
|
|
|
clippy::needless_for_each,
|
2021-09-28 15:33:28 +00:00
|
|
|
clippy::needless_pass_by_value,
|
|
|
|
clippy::option_option,
|
|
|
|
clippy::path_buf_push_overwrite,
|
|
|
|
clippy::ptr_as_ptr,
|
|
|
|
clippy::ref_option_ref,
|
|
|
|
clippy::rest_pat_in_fully_bound_structs,
|
|
|
|
clippy::same_functions_in_if_condition,
|
2021-10-20 14:30:39 +00:00
|
|
|
clippy::semicolon_if_nothing_returned,
|
|
|
|
clippy::single_match_else,
|
2021-09-28 15:33:28 +00:00
|
|
|
clippy::string_add_assign,
|
|
|
|
clippy::string_add,
|
|
|
|
clippy::string_lit_as_bytes,
|
|
|
|
clippy::string_to_string,
|
|
|
|
clippy::todo,
|
|
|
|
clippy::trait_duplication_in_bounds,
|
|
|
|
clippy::unimplemented,
|
|
|
|
clippy::unnested_or_patterns,
|
|
|
|
clippy::unused_self,
|
|
|
|
clippy::useless_transmute,
|
|
|
|
clippy::verbose_file_reads,
|
|
|
|
clippy::zero_sized_map_values,
|
|
|
|
future_incompatible,
|
|
|
|
nonstandard_style,
|
2021-12-26 08:55:13 +00:00
|
|
|
rust_2018_idioms,
|
|
|
|
rustdoc::missing_crate_level_docs
|
2021-09-28 15:33:28 +00:00
|
|
|
)]
|
|
|
|
#![allow(clippy::float_cmp)]
|
|
|
|
#![allow(clippy::manual_range_contains)]
|
2020-07-22 16:01:27 +00:00
|
|
|
|
2019-04-21 08:13:05 +00:00
|
|
|
mod painter;
|
|
|
|
pub use painter::Painter;
|
2020-04-29 19:58:14 +00:00
|
|
|
|
2021-10-19 19:40:55 +00:00
|
|
|
#[cfg(feature = "epi")]
|
|
|
|
mod epi_backend;
|
|
|
|
#[cfg(feature = "epi")]
|
|
|
|
pub use epi_backend::{run, NativeOptions};
|
|
|
|
|
2021-09-28 15:33:28 +00:00
|
|
|
pub use egui_winit;
|
2021-05-08 08:14:56 +00:00
|
|
|
|
2020-05-02 09:37:12 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2021-11-03 19:11:25 +00:00
|
|
|
/// Convenience wrapper for using [`egui`] from a [`glium`] app.
|
2021-04-25 15:02:27 +00:00
|
|
|
pub struct EguiGlium {
|
2022-01-10 22:13:10 +00:00
|
|
|
pub egui_ctx: egui::Context,
|
2021-11-03 12:45:51 +00:00
|
|
|
pub egui_winit: egui_winit::State,
|
|
|
|
pub painter: crate::Painter,
|
2022-01-15 12:59:52 +00:00
|
|
|
|
|
|
|
shapes: Vec<egui::epaint::ClippedShape>,
|
|
|
|
textures_delta: egui::TexturesDelta,
|
2021-04-25 15:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl EguiGlium {
|
|
|
|
pub fn new(display: &glium::Display) -> Self {
|
2022-01-24 13:32:36 +00:00
|
|
|
let painter = crate::Painter::new(display);
|
2021-04-25 15:02:27 +00:00
|
|
|
Self {
|
|
|
|
egui_ctx: Default::default(),
|
2022-01-24 13:32:36 +00:00
|
|
|
egui_winit: egui_winit::State::new(
|
|
|
|
painter.max_texture_side(),
|
|
|
|
display.gl_window().window(),
|
|
|
|
),
|
|
|
|
painter,
|
2022-01-15 12:59:52 +00:00
|
|
|
shapes: Default::default(),
|
|
|
|
textures_delta: Default::default(),
|
2021-04-25 15:02:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:33:28 +00:00
|
|
|
/// Returns `true` if egui wants exclusive use of this event
|
|
|
|
/// (e.g. a mouse click on an egui window, or entering text into a text field).
|
|
|
|
/// For instance, if you use egui for a game, you want to first call this
|
|
|
|
/// and only when this returns `false` pass on the events to your game.
|
|
|
|
///
|
|
|
|
/// Note that egui uses `tab` to move focus between elements, so this will always return `true` for tabs.
|
|
|
|
pub fn on_event(&mut self, event: &glium::glutin::event::WindowEvent<'_>) -> bool {
|
|
|
|
self.egui_winit.on_event(&self.egui_ctx, event)
|
2021-04-25 15:02:27 +00:00
|
|
|
}
|
|
|
|
|
2022-01-15 12:59:52 +00:00
|
|
|
/// Returns `true` if egui requests a repaint.
|
|
|
|
///
|
|
|
|
/// Call [`Self::paint`] later to paint.
|
|
|
|
pub fn run(&mut self, display: &glium::Display, run_ui: impl FnMut(&egui::Context)) -> bool {
|
2021-11-03 12:45:51 +00:00
|
|
|
let raw_input = self
|
|
|
|
.egui_winit
|
|
|
|
.take_egui_input(display.gl_window().window());
|
2021-11-03 19:11:25 +00:00
|
|
|
let (egui_output, shapes) = self.egui_ctx.run(raw_input, run_ui);
|
2021-09-20 19:36:56 +00:00
|
|
|
let needs_repaint = egui_output.needs_repaint;
|
2022-01-15 12:59:52 +00:00
|
|
|
let textures_delta = self.egui_winit.handle_output(
|
|
|
|
display.gl_window().window(),
|
|
|
|
&self.egui_ctx,
|
|
|
|
egui_output,
|
|
|
|
);
|
|
|
|
|
|
|
|
self.shapes = shapes;
|
|
|
|
self.textures_delta.append(textures_delta);
|
|
|
|
needs_repaint
|
2021-04-25 15:02:27 +00:00
|
|
|
}
|
|
|
|
|
2022-01-15 12:59:52 +00:00
|
|
|
/// Paint the results of the last call to [`Self::run`].
|
|
|
|
pub fn paint<T: glium::Surface>(&mut self, display: &glium::Display, target: &mut T) {
|
|
|
|
let shapes = std::mem::take(&mut self.shapes);
|
|
|
|
let mut textures_delta = std::mem::take(&mut self.textures_delta);
|
|
|
|
|
2022-01-22 10:23:12 +00:00
|
|
|
for (id, image_delta) in textures_delta.set {
|
|
|
|
self.painter.set_texture(display, id, &image_delta);
|
2022-01-15 12:59:52 +00:00
|
|
|
}
|
|
|
|
|
2021-04-25 15:02:27 +00:00
|
|
|
let clipped_meshes = self.egui_ctx.tessellate(shapes);
|
|
|
|
self.painter.paint_meshes(
|
|
|
|
display,
|
|
|
|
target,
|
|
|
|
self.egui_ctx.pixels_per_point(),
|
|
|
|
clipped_meshes,
|
|
|
|
);
|
2022-01-15 12:59:52 +00:00
|
|
|
|
|
|
|
for id in textures_delta.free.drain(..) {
|
|
|
|
self.painter.free_texture(id);
|
|
|
|
}
|
2021-04-25 15:02:27 +00:00
|
|
|
}
|
|
|
|
}
|