diff --git a/eframe/src/epi.rs b/eframe/src/epi.rs index 963a8dc7..a5b32d7d 100644 --- a/eframe/src/epi.rs +++ b/eframe/src/epi.rs @@ -365,6 +365,7 @@ impl Default for WebOptions { pub enum Theme { /// Dark mode: light text on a dark background. Dark, + /// Light mode: dark text on a light background. Light, } @@ -389,10 +390,13 @@ impl Theme { pub enum WebGlContextOption { /// Force Use WebGL1. WebGl1, + /// Force use WebGL2. WebGl2, + /// Use WebGl2 first. BestFirst, + /// Use WebGl1 first CompatibilityFirst, } @@ -714,6 +718,7 @@ pub struct IntegrationInfo { pub trait Storage { /// Get the value for the given key. fn get_string(&self, key: &str) -> Option; + /// Set the value for the given key. fn set_string(&mut self, key: &str, value: String); @@ -729,7 +734,9 @@ impl Storage for DummyStorage { fn get_string(&self, _key: &str) -> Option { None } + fn set_string(&mut self, _key: &str, _value: String) {} + fn flush(&mut self) {} } diff --git a/eframe/src/native/epi_integration.rs b/eframe/src/native/epi_integration.rs index f8591213..b2b7d7e2 100644 --- a/eframe/src/native/epi_integration.rs +++ b/eframe/src/native/epi_integration.rs @@ -354,6 +354,7 @@ impl EpiIntegration { #[cfg(feature = "persistence")] const STORAGE_EGUI_MEMORY_KEY: &str = "egui"; + #[cfg(feature = "persistence")] const STORAGE_WINDOW_KEY: &str = "window"; diff --git a/eframe/src/web/backend.rs b/eframe/src/web/backend.rs index 301369ce..a65b982d 100644 --- a/eframe/src/web/backend.rs +++ b/eframe/src/web/backend.rs @@ -360,6 +360,7 @@ pub type AppRunnerRef = Arc>; pub struct AppRunnerContainer { pub runner: AppRunnerRef, + /// Set to `true` if there is a panic. /// Used to ignore callbacks after a panic. pub panicked: Arc, @@ -454,8 +455,10 @@ impl epi::Storage for LocalStorage { fn get_string(&self, key: &str) -> Option { local_storage_get(key) } + fn set_string(&mut self, key: &str, value: String) { local_storage_set(key, &value); } + fn flush(&mut self) {} } diff --git a/egui-wgpu/src/lib.rs b/egui-wgpu/src/lib.rs index 2bbfab86..bd42f342 100644 --- a/egui-wgpu/src/lib.rs +++ b/egui-wgpu/src/lib.rs @@ -15,5 +15,6 @@ pub use renderer::CallbackFn; /// Module for painting [`egui`] with [`wgpu`] on [`winit`]. #[cfg(feature = "winit")] pub mod winit; + #[cfg(feature = "winit")] pub use crate::winit::RenderState; diff --git a/egui-wgpu/src/renderer.rs b/egui-wgpu/src/renderer.rs index 1a36ce07..25fdfe4b 100644 --- a/egui-wgpu/src/renderer.rs +++ b/egui-wgpu/src/renderer.rs @@ -33,6 +33,7 @@ pub struct CallbackFn { } type PrepareCallback = dyn Fn(&wgpu::Device, &wgpu::Queue, &mut TypeMap) + Sync + Send; + type PaintCallback = dyn for<'a, 'b> Fn(PaintCallbackInfo, &'a mut wgpu::RenderPass<'b>, &'b TypeMap) + Sync + Send; diff --git a/egui-winit/src/lib.rs b/egui-winit/src/lib.rs index d50374e3..b9b43980 100644 --- a/egui-winit/src/lib.rs +++ b/egui-winit/src/lib.rs @@ -741,6 +741,7 @@ macro_rules! profile_function { puffin::profile_function!($($arg)*); }; } + #[allow(unused_imports)] pub(crate) use profile_function; @@ -752,5 +753,6 @@ macro_rules! profile_scope { puffin::profile_scope!($($arg)*); }; } + #[allow(unused_imports)] pub(crate) use profile_scope; diff --git a/egui/src/containers/resize.rs b/egui/src/containers/resize.rs index 0e6c6cdd..844fc758 100644 --- a/egui/src/containers/resize.rs +++ b/egui/src/containers/resize.rs @@ -104,11 +104,13 @@ impl Resize { self.min_size = min_size.into(); self } + /// Won't shrink to smaller than this pub fn min_width(mut self, min_width: f32) -> Self { self.min_size.x = min_width; self } + /// Won't shrink to smaller than this pub fn min_height(mut self, min_height: f32) -> Self { self.min_size.y = min_height; diff --git a/egui/src/containers/window.rs b/egui/src/containers/window.rs index 4d5fb43d..40aa0b0d 100644 --- a/egui/src/containers/window.rs +++ b/egui/src/containers/window.rs @@ -102,6 +102,7 @@ impl<'open> Window<'open> { self.resize = self.resize.min_width(min_width); self } + /// Set minimum height of the window. pub fn min_height(mut self, min_height: f32) -> Self { self.resize = self.resize.min_height(min_height); @@ -148,6 +149,7 @@ impl<'open> Window<'open> { self.resize = self.resize.default_width(default_width); self } + /// Set initial height of the window. pub fn default_height(mut self, default_height: f32) -> Self { self.resize = self.resize.default_height(default_height); @@ -760,12 +762,15 @@ fn paint_frame_interaction( struct TitleBar { /// A title Id used for dragging windows id: Id, + /// Prepared text in the title title_galley: WidgetTextGalley, + /// Size of the title bar in a collapsed state (if window is collapsible), /// which includes all necessary space for showing the expand button, the /// title and the close button. min_rect: Rect, + /// Size of the title bar in an expanded state. This size become known only /// after expanding window and painting its content rect: Rect, diff --git a/egui/src/data/input.rs b/egui/src/data/input.rs index 01aa1c6c..49c8c394 100644 --- a/egui/src/data/input.rs +++ b/egui/src/data/input.rs @@ -138,6 +138,7 @@ impl RawInput { pub struct HoveredFile { /// Set by the `egui-winit` backend. pub path: Option, + /// With the `eframe` web backend, this is set to the mime-type of the file (if available). pub mime: String, } @@ -148,10 +149,13 @@ pub struct HoveredFile { pub struct DroppedFile { /// Set by the `egui-winit` backend. pub path: Option, + /// Name of the file. Set by the `eframe` web backend. pub name: String, + /// Set by the `eframe` web backend. pub last_modified: Option, + /// Set by the `eframe` web backend. pub bytes: Option>, } @@ -164,19 +168,25 @@ pub struct DroppedFile { pub enum Event { /// The integration detected a "copy" event (e.g. Cmd+C). Copy, + /// The integration detected a "cut" event (e.g. Cmd+X). Cut, + /// The integration detected a "paste" event (e.g. Cmd+V). Paste(String), + /// Text input, e.g. via keyboard. /// /// When the user presses enter/return, do not send a [`Text`](Event::Text) (just [`Key::Enter`]). Text(String), + /// A key was pressed or released. Key { key: Key, + /// Was it pressed or released? pressed: bool, + /// The state of the modifier keys at the time of the event. modifiers: Modifiers, }, @@ -188,13 +198,17 @@ pub enum Event { PointerButton { /// Where is the pointer? pos: Pos2, + /// What mouse button? For touches, use [`PointerButton::Primary`]. button: PointerButton, + /// Was it the button/touch pressed this frame, or released? pressed: bool, + /// The state of the modifier keys at the time of the event. modifiers: Modifiers, }, + /// The mouse left the screen, or the last/primary touch input disappeared. /// /// This means there is no longer a cursor on the screen for hovering etc. @@ -225,8 +239,10 @@ pub enum Event { /// IME composition start. CompositionStart, + /// A new IME candidate is being suggested. CompositionUpdate(String), + /// IME composition ended with this final result. CompositionEnd(String), @@ -236,13 +252,17 @@ pub enum Event { /// Hashed device identifier (if available; may be zero). /// Can be used to separate touches from different devices. device_id: TouchDeviceId, + /// Unique identifier of a finger/pen. Value is stable from touch down /// to lift-up id: TouchId, + /// One of: start move end cancel. phase: TouchPhase, + /// Position of the touch (or where the touch was last detected) pos: Pos2, + /// Describes how hard the touch device was pressed. May always be `0` if the platform does /// not support pressure sensitivity. /// The value is in the range from 0.0 (no pressure) to 1.0 (maximum pressure). @@ -256,13 +276,17 @@ pub enum Event { pub enum PointerButton { /// The primary mouse button is usually the left one. Primary = 0, + /// The secondary mouse button is usually the right one, /// and most often used for context menus or other optional things. Secondary = 1, + /// The tertiary mouse button is usually the middle mouse button (e.g. clicking the scroll wheel). Middle = 2, + /// The first extra mouse button on some mice. In web typically corresponds to the Browser back button. Extra1 = 3, + /// The second extra mouse button on some mice. In web typically corresponds to the Browser forward button. Extra2 = 4, } @@ -337,6 +361,7 @@ impl Modifiers { mac_cmd: false, command: false, }; + /// The Mac ⌘ Command key pub const MAC_CMD: Self = Self { alt: false, @@ -345,6 +370,7 @@ impl Modifiers { mac_cmd: true, command: false, }; + /// On Mac: ⌘ Command key, elsewhere: Ctrl key pub const COMMAND: Self = Self { alt: false, @@ -426,6 +452,7 @@ impl Modifiers { impl std::ops::BitOr for Modifiers { type Output = Self; + fn bitor(self, rhs: Self) -> Self { Self { alt: self.alt | rhs.alt, @@ -593,12 +620,15 @@ pub struct TouchId(pub u64); pub enum TouchPhase { /// User just placed a touch point on the touch surface Start, + /// User moves a touch point along the surface. This event is also sent when /// any attributes (position, force, …) of the touch point change. Move, + /// User lifted the finger or pen from the surface, or slid off the edge of /// the surface End, + /// Touch operation has been disrupted by something (various reasons are possible, /// maybe a pop-up alert or any other kind of interruption which may not have /// been intended by the user) diff --git a/egui/src/data/output.rs b/egui/src/data/output.rs index 81349b86..405181a6 100644 --- a/egui/src/data/output.rs +++ b/egui/src/data/output.rs @@ -143,10 +143,12 @@ impl PlatformOutput { } } +/// What URL to open, and how. #[derive(Clone, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct OpenUrl { pub url: String, + /// If `true`, open the url in a new tab. /// If `false` open it in the same tab. /// Only matters when in a web browser. @@ -247,10 +249,13 @@ pub enum CursorIcon { // Resizing in two directions: /// Horizontal resize `-` to make something wider or more narrow (left to/from right) ResizeHorizontal, + /// Diagonal resize `/` (right-up to/from left-down) ResizeNeSw, + /// Diagonal resize `\` (left-up to/from right-down) ResizeNwSe, + /// Vertical resize `|` (up-down or down-up) ResizeVertical, @@ -258,24 +263,32 @@ pub enum CursorIcon { // Resizing in one direction: /// Resize something rightwards (e.g. when dragging the right-most edge of something) ResizeEast, + /// Resize something down and right (e.g. when dragging the bottom-right corner of something) ResizeSouthEast, + /// Resize something downwards (e.g. when dragging the bottom edge of something) ResizeSouth, + /// Resize something down and left (e.g. when dragging the bottom-left corner of something) ResizeSouthWest, + /// Resize something leftwards (e.g. when dragging the left edge of something) ResizeWest, + /// Resize something up and left (e.g. when dragging the top-left corner of something) ResizeNorthWest, + /// Resize something up (e.g. when dragging the top edge of something) ResizeNorth, + /// Resize something up and right (e.g. when dragging the top-right corner of something) ResizeNorthEast, // ------------------------------------ /// Resize a column ResizeColumn, + /// Resize a row ResizeRow, @@ -283,6 +296,7 @@ pub enum CursorIcon { // Zooming: /// Enhance! ZoomIn, + /// Let's get a better overview ZoomOut, } @@ -339,17 +353,22 @@ impl Default for CursorIcon { #[derive(Clone, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum OutputEvent { - // A widget was clicked. + /// A widget was clicked. Clicked(WidgetInfo), - // A widget was double-clicked. + + /// A widget was double-clicked. DoubleClicked(WidgetInfo), - // A widget was triple-clicked. + + /// A widget was triple-clicked. TripleClicked(WidgetInfo), + /// A widget gained keyboard focus (by tab key). FocusGained(WidgetInfo), - // Text selection was updated. + + /// Text selection was updated. TextSelectionChanged(WidgetInfo), - // A widget's value changed. + + /// A widget's value changed. ValueChanged(WidgetInfo), } @@ -372,19 +391,26 @@ impl std::fmt::Debug for OutputEvent { pub struct WidgetInfo { /// The type of widget this is. pub typ: WidgetType, - // Whether the widget is enabled. + + /// Whether the widget is enabled. pub enabled: bool, + /// The text on labels, buttons, checkboxes etc. pub label: Option, + /// The contents of some editable text (for [`TextEdit`](crate::TextEdit) fields). pub current_text_value: Option, - // The previous text value. + + /// The previous text value. pub prev_text_value: Option, + /// The current value of checkboxes and radio buttons. pub selected: Option, + /// The current value of sliders etc. pub value: Option, - // Selected range of characters in [`Self::current_text_value`]. + + /// Selected range of characters in [`Self::current_text_value`]. pub text_selection: Option>, } diff --git a/egui/src/grid.rs b/egui/src/grid.rs index 0e9d77ae..fbfd7820 100644 --- a/egui/src/grid.rs +++ b/egui/src/grid.rs @@ -110,6 +110,7 @@ impl GridLayout { .col_width(col) .unwrap_or(self.min_cell_size.x) } + fn prev_row_height(&self, row: usize) -> f32 { self.prev_state .row_height(row) diff --git a/egui/src/id.rs b/egui/src/id.rs index d8d3ef35..b83d911c 100644 --- a/egui/src/id.rs +++ b/egui/src/id.rs @@ -91,9 +91,11 @@ impl std::hash::Hasher for IdHasher { fn write_u8(&mut self, _n: u8) { unreachable!("Invalid use of IdHasher"); } + fn write_u16(&mut self, _n: u16) { unreachable!("Invalid use of IdHasher"); } + fn write_u32(&mut self, _n: u32) { unreachable!("Invalid use of IdHasher"); } @@ -110,15 +112,19 @@ impl std::hash::Hasher for IdHasher { fn write_i8(&mut self, _n: i8) { unreachable!("Invalid use of IdHasher"); } + fn write_i16(&mut self, _n: i16) { unreachable!("Invalid use of IdHasher"); } + fn write_i32(&mut self, _n: i32) { unreachable!("Invalid use of IdHasher"); } + fn write_i64(&mut self, _n: i64) { unreachable!("Invalid use of IdHasher"); } + fn write_isize(&mut self, _n: isize) { unreachable!("Invalid use of IdHasher"); } diff --git a/egui/src/input_state.rs b/egui/src/input_state.rs index c3f7e5ed..ed40c5ca 100644 --- a/egui/src/input_state.rs +++ b/egui/src/input_state.rs @@ -399,6 +399,7 @@ impl Click { pub fn is_double(&self) -> bool { self.count == 2 } + pub fn is_triple(&self) -> bool { self.count == 3 } @@ -418,9 +419,11 @@ impl PointerEvent { pub fn is_press(&self) -> bool { matches!(self, PointerEvent::Pressed { .. }) } + pub fn is_release(&self) -> bool { matches!(self, PointerEvent::Released(_)) } + pub fn is_click(&self) -> bool { matches!(self, PointerEvent::Released(Some(_click))) } diff --git a/egui/src/input_state/touch_state.rs b/egui/src/input_state/touch_state.rs index 248f1ff3..e4a7a1f0 100644 --- a/egui/src/input_state/touch_state.rs +++ b/egui/src/input_state/touch_state.rs @@ -68,6 +68,7 @@ pub(crate) struct TouchState { /// Technical identifier of the touch device. This is used to identify relevant touch events /// for this [`TouchState`] instance. device_id: TouchDeviceId, + /// Active touches, if any. /// /// TouchId is the unique identifier of the touch. It is valid as long as the finger/pen touches the surface. The @@ -75,6 +76,7 @@ pub(crate) struct TouchState { /// /// Refer to [`ActiveTouch`]. active_touches: BTreeMap, + /// If a gesture has been recognized (i.e. when exactly two fingers touch the surface), this /// holds state information gesture_state: Option, @@ -107,6 +109,7 @@ struct DynGestureState { struct ActiveTouch { /// Current position of this touch, in device coordinates (not necessarily screen position) pos: Pos2, + /// Current force of the touch. A value in the interval [0.0 .. 1.0] /// /// Note that a value of 0.0 either indicates a very light touch, or it means that the device diff --git a/egui/src/layers.rs b/egui/src/layers.rs index bd009046..632dc33c 100644 --- a/egui/src/layers.rs +++ b/egui/src/layers.rs @@ -10,16 +10,21 @@ use epaint::{ClippedShape, Shape}; pub enum Order { /// Painted behind all floating windows Background, + /// Special layer between panels and windows PanelResizeLine, + /// Normal moveable windows that you reorder by click Middle, + /// Popups, menus etc that should always be painted on top of windows /// Foreground objects can also have tooltips Foreground, + /// Things floating on top of everything else, like tooltips. /// You cannot interact with these. Tooltip, + /// Debug layer, always painted last / on top Debug, } diff --git a/egui/src/lib.rs b/egui/src/lib.rs index f0a09725..26059400 100644 --- a/egui/src/lib.rs +++ b/egui/src/lib.rs @@ -479,15 +479,19 @@ macro_rules! egui_assert { pub mod special_emojis { /// Tux, the Linux penguin. pub const OS_LINUX: char = '🐧'; + /// The Windows logo. pub const OS_WINDOWS: char = ''; + /// The Android logo. pub const OS_ANDROID: char = ''; + /// The Apple logo. pub const OS_APPLE: char = ''; /// The Github logo. pub const GITHUB: char = ''; + /// The Twitter bird. pub const TWITTER: char = ''; diff --git a/egui/src/menu.rs b/egui/src/menu.rs index c4beb1fb..a3812f3e 100644 --- a/egui/src/menu.rs +++ b/egui/src/menu.rs @@ -49,12 +49,15 @@ impl BarState { self.open_menu.show(response, add_contents) } } + impl std::ops::Deref for BarState { type Target = MenuRootManager; + fn deref(&self) -> &Self::Target { &self.open_menu } } + impl std::ops::DerefMut for BarState { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.open_menu @@ -194,6 +197,7 @@ pub(crate) fn context_menu( pub(crate) struct MenuRootManager { inner: Option, } + impl MenuRootManager { /// Show a menu at pointer if right-clicked response. /// Should be called from [`Context`] on a [`Response`] @@ -212,16 +216,20 @@ impl MenuRootManager { None } } + fn is_menu_open(&self, id: Id) -> bool { self.inner.as_ref().map(|m| m.id) == Some(id) } } + impl std::ops::Deref for MenuRootManager { type Target = Option; + fn deref(&self) -> &Self::Target { &self.inner } } + impl std::ops::DerefMut for MenuRootManager { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner @@ -242,6 +250,7 @@ impl MenuRoot { id, } } + pub fn show( &mut self, response: &Response, @@ -349,22 +358,26 @@ impl MenuRoot { Self::handle_menu_response(root, menu_response); } } + #[derive(Copy, Clone, PartialEq)] pub(crate) enum MenuResponse { Close, Stay, Create(Pos2, Id), } + impl MenuResponse { pub fn is_close(&self) -> bool { *self == Self::Close } } + pub struct SubMenuButton { text: WidgetText, icon: WidgetText, index: usize, } + impl SubMenuButton { /// The `icon` can be an emoji (e.g. `⏵` right arrow), shown right of the label fn new(text: impl Into, icon: impl Into, index: usize) -> Self { @@ -442,10 +455,12 @@ impl SubMenuButton { response } } + pub struct SubMenu { button: SubMenuButton, parent_state: Arc>, } + impl SubMenu { fn new(parent_state: Arc>, text: impl Into) -> Self { let index = parent_state.write().next_entry_index(); @@ -472,16 +487,21 @@ impl SubMenu { InnerResponse::new(inner, button) } } + pub(crate) struct MenuState { /// The opened sub-menu and its [`Id`] sub_menu: Option<(Id, Arc>)>, + /// Bounding box of this menu (without the sub-menu) pub rect: Rect, + /// Used to check if any menu in the tree wants to close pub response: MenuResponse, + /// Used to hash different [`Id`]s for sub-menus entry_count: usize, } + impl MenuState { pub fn new(position: Pos2) -> Self { Self { @@ -491,10 +511,12 @@ impl MenuState { entry_count: 0, } } + /// Close menu hierarchy. pub fn close(&mut self) { self.response = MenuResponse::Close; } + pub fn show( ctx: &Context, menu_state: &Arc>, @@ -503,6 +525,7 @@ impl MenuState { ) -> InnerResponse { crate::menu::menu_ui(ctx, id, menu_state, add_contents) } + fn show_submenu( &mut self, ctx: &Context, @@ -516,6 +539,7 @@ impl MenuState { self.cascade_close_response(sub_response); Some(response) } + /// Check if position is in the menu hierarchy's area. pub fn area_contains(&self, pos: Pos2) -> bool { self.rect.contains(pos) @@ -524,10 +548,12 @@ impl MenuState { .as_ref() .map_or(false, |(_, sub)| sub.read().area_contains(pos)) } + fn next_entry_index(&mut self) -> usize { self.entry_count += 1; self.entry_count - 1 } + /// Sense button interaction opening and closing submenu. fn submenu_button_interaction(&mut self, ui: &mut Ui, sub_id: Id, button: &Response) { let pointer = &ui.input().pointer.clone(); @@ -542,6 +568,7 @@ impl MenuState { self.close_submenu(); } } + /// Check if `dir` points from `pos` towards left side of `rect`. fn points_at_left_of_rect(pos: Pos2, dir: Vec2, rect: Rect) -> bool { let vel_a = dir.angle(); @@ -549,6 +576,7 @@ impl MenuState { let bottom_a = (rect.left_bottom() - pos).angle(); bottom_a - vel_a >= 0.0 && top_a - vel_a <= 0.0 } + /// Check if pointer is moving towards current submenu. fn moving_towards_current_submenu(&self, pointer: &PointerState) -> bool { if pointer.is_still() { @@ -561,6 +589,7 @@ impl MenuState { } false } + /// Check if pointer is hovering current submenu. fn hovering_current_submenu(&self, pointer: &PointerState) -> bool { if let Some(sub_menu) = self.get_current_submenu() { @@ -570,32 +599,39 @@ impl MenuState { } false } + /// Cascade close response to menu root. fn cascade_close_response(&mut self, response: MenuResponse) { if response.is_close() { self.response = response; } } + fn is_open(&self, id: Id) -> bool { self.get_sub_id() == Some(id) } + fn get_sub_id(&self) -> Option { self.sub_menu.as_ref().map(|(id, _)| *id) } + fn get_current_submenu(&self) -> Option<&Arc>> { self.sub_menu.as_ref().map(|(_, sub)| sub) } + fn get_submenu(&mut self, id: Id) -> Option<&Arc>> { self.sub_menu .as_ref() .and_then(|(k, sub)| if id == *k { Some(sub) } else { None }) } + /// Open submenu at position, if not already open. fn open_submenu(&mut self, id: Id, pos: Pos2) { if !self.is_open(id) { self.sub_menu = Some((id, Arc::new(RwLock::new(MenuState::new(pos))))); } } + fn close_submenu(&mut self) { self.sub_menu = None; } diff --git a/egui/src/response.rs b/egui/src/response.rs index f1c72bd8..9e62a45b 100644 --- a/egui/src/response.rs +++ b/egui/src/response.rs @@ -603,6 +603,7 @@ impl Response { /// Now `draw_vec2(ui, foo).hovered` is true if either [`DragValue`](crate::DragValue) were hovered. impl std::ops::BitOr for Response { type Output = Self; + fn bitor(self, rhs: Self) -> Self { self.union(rhs) } @@ -644,6 +645,7 @@ impl std::ops::BitOrAssign for Response { pub struct InnerResponse { /// What the user closure returned. pub inner: R, + /// The response of the area. pub response: Response, } diff --git a/egui/src/style.rs b/egui/src/style.rs index 37b20d6a..2ca8b3ba 100644 --- a/egui/src/style.rs +++ b/egui/src/style.rs @@ -367,6 +367,7 @@ impl From for Margin { impl std::ops::Add for Margin { type Output = Self; + fn add(self, other: Self) -> Self { Self { left: self.left + other.left, @@ -524,12 +525,16 @@ pub struct Widgets { /// * `noninteractive.bg_fill` is the background color of windows. /// * `noninteractive.fg_stroke` is the normal text color. pub noninteractive: WidgetVisuals, + /// The style of an interactive widget, such as a button, at rest. pub inactive: WidgetVisuals, + /// The style of an interactive widget while you hover it. pub hovered: WidgetVisuals, + /// The style of an interactive widget as you are clicking or dragging it. pub active: WidgetVisuals, + /// The style of a button that has an open menu beneath it (e.g. a combo-box) pub open: WidgetVisuals, } @@ -721,6 +726,7 @@ impl Selection { stroke: Stroke::new(1.0, Color32::from_rgb(192, 222, 255)), } } + fn light() -> Self { Self { bg_fill: Color32::from_rgb(144, 209, 255), diff --git a/egui/src/util/id_type_map.rs b/egui/src/util/id_type_map.rs index fccbeaf0..735ab487 100644 --- a/egui/src/util/id_type_map.rs +++ b/egui/src/util/id_type_map.rs @@ -78,10 +78,12 @@ enum Element { #[cfg(feature = "persistence")] serialize_fn: Option, }, + /// A serialized value Serialized { /// The type of value we are storing. type_id: TypeId, + /// The ron data we can deserialize. ron: Arc, }, @@ -512,6 +514,7 @@ impl PersistedMap { .collect(), ) } + fn into_map(self) -> IdTypeMap { IdTypeMap( self.0 diff --git a/egui/src/widgets/mod.rs b/egui/src/widgets/mod.rs index c56c2caa..f782056b 100644 --- a/egui/src/widgets/mod.rs +++ b/egui/src/widgets/mod.rs @@ -94,6 +94,7 @@ pub trait WidgetWithState { pub fn reset_button(ui: &mut Ui, value: &mut T) { reset_button_with(ui, value, T::default()); } + /// Show a button to reset a value to its default. /// The button is only enabled if the value does not already have its original value. pub fn reset_button_with(ui: &mut Ui, value: &mut T, reset_value: T) { diff --git a/egui/src/widgets/plot/items/mod.rs b/egui/src/widgets/plot/items/mod.rs index ffb1bd5a..c9f66772 100644 --- a/egui/src/widgets/plot/items/mod.rs +++ b/egui/src/widgets/plot/items/mod.rs @@ -33,12 +33,19 @@ pub(super) struct PlotConfig<'a> { /// Trait shared by things that can be drawn in the plot. pub(super) trait PlotItem { fn get_shapes(&self, ui: &mut Ui, transform: &ScreenTransform, shapes: &mut Vec); + fn initialize(&mut self, x_range: RangeInclusive); + fn name(&self) -> &str; + fn color(&self) -> Color32; + fn highlight(&mut self); + fn highlighted(&self) -> bool; + fn geometry(&self) -> PlotGeometry<'_>; + fn get_bounds(&self) -> PlotBounds; fn find_closest(&self, point: Pos2, transform: &ScreenTransform) -> Option { diff --git a/egui/src/widgets/plot/items/rect_elem.rs b/egui/src/widgets/plot/items/rect_elem.rs index fa9ce441..0379a416 100644 --- a/egui/src/widgets/plot/items/rect_elem.rs +++ b/egui/src/widgets/plot/items/rect_elem.rs @@ -6,7 +6,9 @@ use epaint::{Color32, Rgba, Stroke}; /// Trait that abstracts from rectangular 'Value'-like elements, such as bars or boxes pub(super) trait RectElement { fn name(&self) -> &str; + fn bounds_min(&self) -> PlotPoint; + fn bounds_max(&self) -> PlotPoint; fn bounds(&self) -> PlotBounds { diff --git a/egui/src/widgets/plot/items/values.rs b/egui/src/widgets/plot/items/values.rs index d28ac008..95c21dbe 100644 --- a/egui/src/widgets/plot/items/values.rs +++ b/egui/src/widgets/plot/items/values.rs @@ -12,6 +12,7 @@ pub struct PlotPoint { /// This is often something monotonically increasing, such as time, but doesn't have to be. /// Goes from left to right. pub x: f64, + /// Goes from bottom to top (inverse of everything else in egui!). pub y: f64, } diff --git a/egui/src/widgets/plot/transform.rs b/egui/src/widgets/plot/transform.rs index b4a77fba..584d0a0a 100644 --- a/egui/src/widgets/plot/transform.rs +++ b/egui/src/widgets/plot/transform.rs @@ -167,10 +167,13 @@ impl PlotBounds { pub(crate) struct ScreenTransform { /// The screen rectangle. frame: Rect, + /// The plot bounds. bounds: PlotBounds, + /// Whether to always center the x-range of the bounds. x_centered: bool, + /// Whether to always center the y-range of the bounds. y_centered: bool, } diff --git a/egui/src/widgets/slider.rs b/egui/src/widgets/slider.rs index aaf73359..1534a5bd 100644 --- a/egui/src/widgets/slider.rs +++ b/egui/src/widgets/slider.rs @@ -27,9 +27,11 @@ fn set(get_set_value: &mut GetSetValue<'_>, value: f64) { #[derive(Clone)] struct SliderSpec { logarithmic: bool, + /// For logarithmic sliders, the smallest positive value we are interested in. /// 1 for integer sliders, maybe 1e-6 for others. smallest_positive: f64, + /// For logarithmic sliders, the largest positive value we are interested in /// before the slider switches to `INFINITY`, if that is the higher end. /// Default: INFINITY. diff --git a/egui_demo_lib/src/color_test.rs b/egui_demo_lib/src/color_test.rs index bb6b69e3..3817e604 100644 --- a/egui_demo_lib/src/color_test.rs +++ b/egui_demo_lib/src/color_test.rs @@ -265,9 +265,11 @@ impl Gradient { pub fn one_color(srgba: Color32) -> Self { Self(vec![srgba, srgba]) } + pub fn texture_gradient(left: Color32, right: Color32) -> Self { Self(vec![left, right]) } + pub fn ground_truth_linear_gradient(left: Color32, right: Color32) -> Self { let left = Rgba::from(left); let right = Rgba::from(right); @@ -282,6 +284,7 @@ impl Gradient { .collect(), ) } + /// This is how a bad person blends `sRGBA` pub fn ground_truth_bad_srgba_gradient(left: Color32, right: Color32) -> Self { let n = 255; diff --git a/egui_demo_lib/src/demo/context_menu.rs b/egui_demo_lib/src/demo/context_menu.rs index bd951234..f8b6bc58 100644 --- a/egui_demo_lib/src/demo/context_menu.rs +++ b/egui_demo_lib/src/demo/context_menu.rs @@ -10,6 +10,7 @@ fn gaussian(x: f64) -> f64 { let var: f64 = 2.0; f64::exp(-(x / var).powi(2)) / (var * f64::sqrt(std::f64::consts::TAU)) } + fn sigmoid(x: f64) -> f64 { -1.0 + 2.0 / (1.0 + f64::exp(-x)) } diff --git a/egui_demo_lib/src/demo/drag_and_drop.rs b/egui_demo_lib/src/demo/drag_and_drop.rs index c811ba0c..49bf62f4 100644 --- a/egui_demo_lib/src/demo/drag_and_drop.rs +++ b/egui_demo_lib/src/demo/drag_and_drop.rs @@ -75,12 +75,14 @@ pub fn drop_target( InnerResponse::new(ret, response) } + #[derive(Clone, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct DragAndDropDemo { /// columns with items columns: Vec>, } + impl Default for DragAndDropDemo { fn default() -> Self { Self { diff --git a/egui_demo_lib/src/demo/layout_test.rs b/egui_demo_lib/src/demo/layout_test.rs index 39fab0ea..60193d9f 100644 --- a/egui_demo_lib/src/demo/layout_test.rs +++ b/egui_demo_lib/src/demo/layout_test.rs @@ -47,6 +47,7 @@ impl LayoutSettings { cross_justify: false, } } + fn top_down_justified_centered() -> Self { Self { main_dir: Direction::TopDown, @@ -55,6 +56,7 @@ impl LayoutSettings { cross_justify: true, } } + fn horizontal_wrapped() -> Self { Self { main_dir: Direction::LeftToRight, diff --git a/egui_demo_lib/src/demo/misc_demo_window.rs b/egui_demo_lib/src/demo/misc_demo_window.rs index 85cdaff6..80d793a8 100644 --- a/egui_demo_lib/src/demo/misc_demo_window.rs +++ b/egui_demo_lib/src/demo/misc_demo_window.rs @@ -426,6 +426,7 @@ impl Tree { Tree(vec![Tree(vec![Tree::default(); 2]); 3]), ]) } + pub fn ui(&mut self, ui: &mut Ui) -> Action { self.ui_impl(ui, 0, "root") } diff --git a/egui_demo_lib/src/demo/paint_bezier.rs b/egui_demo_lib/src/demo/paint_bezier.rs index 4cbd56da..65877c4c 100644 --- a/egui_demo_lib/src/demo/paint_bezier.rs +++ b/egui_demo_lib/src/demo/paint_bezier.rs @@ -6,6 +6,7 @@ use egui::*; pub struct PaintBezier { /// Bézier curve degree, it can be 3, 4. degree: usize, + /// The control points. The [`Self::degree`] first of them are used. control_points: [Pos2; 4], diff --git a/egui_demo_lib/src/demo/plot_demo.rs b/egui_demo_lib/src/demo/plot_demo.rs index c07d1e9d..709e2fdd 100644 --- a/egui_demo_lib/src/demo/plot_demo.rs +++ b/egui_demo_lib/src/demo/plot_demo.rs @@ -265,6 +265,7 @@ impl LegendDemo { 100, )) } + fn sin() -> Line { Line::new(PlotPoints::from_explicit_callback( move |x| x.sin(), @@ -272,6 +273,7 @@ impl LegendDemo { 100, )) } + fn cos() -> Line { Line::new(PlotPoints::from_explicit_callback( move |x| x.cos(), @@ -390,12 +392,15 @@ impl CustomAxisDemo { fn get_day(x: f64) -> f64 { (x / MINS_PER_DAY).floor() } + fn get_hour(x: f64) -> f64 { (x.rem_euclid(MINS_PER_DAY) / MINS_PER_H).floor() } + fn get_minute(x: f64) -> f64 { x.rem_euclid(MINS_PER_H).floor() } + fn get_percent(y: f64) -> f64 { 100.0 * y } @@ -476,6 +481,7 @@ impl LinkedAxisDemo { 100, )) } + fn sin() -> Line { Line::new(PlotPoints::from_explicit_callback( move |x| x.sin(), @@ -483,6 +489,7 @@ impl LinkedAxisDemo { 100, )) } + fn cos() -> Line { Line::new(PlotPoints::from_explicit_callback( move |x| x.cos(), diff --git a/egui_demo_lib/src/easy_mark/easy_mark_parser.rs b/egui_demo_lib/src/easy_mark/easy_mark_parser.rs index b4301853..3d64d12c 100644 --- a/egui_demo_lib/src/easy_mark/easy_mark_parser.rs +++ b/egui_demo_lib/src/easy_mark/easy_mark_parser.rs @@ -12,20 +12,28 @@ pub enum Item<'a> { /// `\n` // TODO(emilk): add Style here so empty heading still uses up the right amount of space. Newline, + /// Text(Style, &'a str), + /// title, url Hyperlink(Style, &'a str, &'a str), + /// leading space before e.g. a [`Self::BulletPoint`]. Indentation(usize), + /// > QuoteIndent, + /// - a point well made. BulletPoint, + /// 1. numbered list. The string is the number(s). NumberedPoint(&'a str), + /// --- Separator, + /// language, code CodeBlock(&'a str, &'a str), } @@ -34,20 +42,28 @@ pub enum Item<'a> { pub struct Style { /// # heading (large text) pub heading: bool, + /// > quoted (slightly dimmer color or other font style) pub quoted: bool, + /// `code` (monospace, some other color) pub code: bool, + /// self.strong* (emphasized, e.g. bold) pub strong: bool, + /// _underline_ pub underline: bool, + /// ~strikethrough~ pub strikethrough: bool, + /// /italics/ pub italics: bool, + /// $small$ pub small: bool, + /// ^raised^ pub raised: bool, } @@ -66,8 +82,10 @@ pub struct Style { pub struct Parser<'a> { /// The remainder of the input text s: &'a str, + /// Are we at the start of a line? start_of_line: bool, + /// Current self.style. Reset after a newline. style: Style, } diff --git a/egui_extras/src/image.rs b/egui_extras/src/image.rs index 9c8fb3be..54310e30 100644 --- a/egui_extras/src/image.rs +++ b/egui_extras/src/image.rs @@ -15,6 +15,7 @@ pub struct RetainedImage { texture: Mutex>, filter: TextureFilter, } + impl RetainedImage { pub fn from_color_image(debug_name: impl Into, image: ColorImage) -> Self { Self { diff --git a/egui_extras/src/layout.rs b/egui_extras/src/layout.rs index 895b7ac9..56ae547d 100644 --- a/egui_extras/src/layout.rs +++ b/egui_extras/src/layout.rs @@ -4,6 +4,7 @@ use egui::{Pos2, Rect, Response, Sense, Ui}; pub(crate) enum CellSize { /// Absolute size in points Absolute(f32), + /// Take all available space Remainder, } @@ -20,6 +21,7 @@ pub(crate) enum CellSize { pub(crate) enum CellDirection { /// Cells go from left to right. Horizontal, + /// Cells go from top to bottom. Vertical, } @@ -55,6 +57,7 @@ impl<'l> StripLayout<'l> { cell_layout, } } + fn cell_rect(&self, width: &CellSize, height: &CellSize) -> Rect { Rect { min: self.cursor, diff --git a/egui_extras/src/sizing.rs b/egui_extras/src/sizing.rs index 150d913d..8a58302d 100644 --- a/egui_extras/src/sizing.rs +++ b/egui_extras/src/sizing.rs @@ -3,8 +3,10 @@ pub enum Size { /// Absolute size in points, with a given range of allowed sizes to resize within. Absolute { initial: f32, range: (f32, f32) }, + /// Relative size relative to all available space. Relative { fraction: f32, range: (f32, f32) }, + /// Multiple remainders each get the same space. Remainder { range: (f32, f32) }, } diff --git a/egui_glow/src/painter.rs b/egui_glow/src/painter.rs index e6dfb429..de2bfb20 100644 --- a/egui_glow/src/painter.rs +++ b/egui_glow/src/painter.rs @@ -25,6 +25,7 @@ pub type TextureFilter = egui::TextureFilter; trait TextureFilterExt { fn glow_code(&self) -> u32; } + impl TextureFilterExt for TextureFilter { fn glow_code(&self) -> u32 { match self { diff --git a/egui_glow/src/shader_version.rs b/egui_glow/src/shader_version.rs index 86749e3d..d49dfe7d 100644 --- a/egui_glow/src/shader_version.rs +++ b/egui_glow/src/shader_version.rs @@ -60,6 +60,7 @@ impl ShaderVersion { Self::Es300 => "#version 300 es\n", } } + pub(crate) fn is_new_shader_interface(&self) -> &'static str { match self { ShaderVersion::Es300 | ShaderVersion::Gl140 => "#define NEW_SHADER_INTERFACE\n", diff --git a/emath/src/align.rs b/emath/src/align.rs index 016b7d71..5a09f8ac 100644 --- a/emath/src/align.rs +++ b/emath/src/align.rs @@ -19,10 +19,13 @@ pub enum Align { impl Align { /// Convenience for [`Self::Min`] pub const LEFT: Self = Self::Min; + /// Convenience for [`Self::Max`] pub const RIGHT: Self = Self::Max; + /// Convenience for [`Self::Min`] pub const TOP: Self = Self::Min; + /// Convenience for [`Self::Max`] pub const BOTTOM: Self = Self::Max; diff --git a/emath/src/lib.rs b/emath/src/lib.rs index 78b9fb6d..016e3e8d 100644 --- a/emath/src/lib.rs +++ b/emath/src/lib.rs @@ -51,12 +51,14 @@ pub use { pub trait One { fn one() -> Self; } + impl One for f32 { #[inline(always)] fn one() -> Self { 1.0 } } + impl One for f64 { #[inline(always)] fn one() -> Self { @@ -78,6 +80,7 @@ pub trait Real: } impl Real for f32 {} + impl Real for f64 {} // ---------------------------------------------------------------------------- @@ -251,6 +254,7 @@ macro_rules! impl_num_ext { fn at_least(self, lower_limit: Self) -> Self { self.max(lower_limit) } + #[inline(always)] fn at_most(self, upper_limit: Self) -> Self { self.min(upper_limit) diff --git a/emath/src/rect.rs b/emath/src/rect.rs index 26b79450..887c09f1 100644 --- a/emath/src/rect.rs +++ b/emath/src/rect.rs @@ -415,11 +415,13 @@ impl Rect { pub fn left(&self) -> f32 { self.min.x } + /// `min.x` #[inline(always)] pub fn left_mut(&mut self) -> &mut f32 { &mut self.min.x } + /// `min.x` #[inline(always)] pub fn set_left(&mut self, x: f32) { @@ -431,11 +433,13 @@ impl Rect { pub fn right(&self) -> f32 { self.max.x } + /// `max.x` #[inline(always)] pub fn right_mut(&mut self) -> &mut f32 { &mut self.max.x } + /// `max.x` #[inline(always)] pub fn set_right(&mut self, x: f32) { @@ -447,11 +451,13 @@ impl Rect { pub fn top(&self) -> f32 { self.min.y } + /// `min.y` #[inline(always)] pub fn top_mut(&mut self) -> &mut f32 { &mut self.min.y } + /// `min.y` #[inline(always)] pub fn set_top(&mut self, y: f32) { @@ -463,11 +469,13 @@ impl Rect { pub fn bottom(&self) -> f32 { self.max.y } + /// `max.y` #[inline(always)] pub fn bottom_mut(&mut self) -> &mut f32 { &mut self.max.y } + /// `max.y` #[inline(always)] pub fn set_bottom(&mut self, y: f32) { diff --git a/emath/src/rect_transform.rs b/emath/src/rect_transform.rs index 5c5977d9..9d700b99 100644 --- a/emath/src/rect_transform.rs +++ b/emath/src/rect_transform.rs @@ -67,6 +67,7 @@ impl RectTransform { /// Transforms the position. impl std::ops::Mul for RectTransform { type Output = Pos2; + fn mul(self, pos: Pos2) -> Pos2 { self.transform_pos(pos) } @@ -75,6 +76,7 @@ impl std::ops::Mul for RectTransform { /// Transforms the position. impl std::ops::Mul for &RectTransform { type Output = Pos2; + fn mul(self, pos: Pos2) -> Pos2 { self.transform_pos(pos) } diff --git a/emath/src/rot2.rs b/emath/src/rot2.rs index 3ff84305..e29f18f4 100644 --- a/emath/src/rot2.rs +++ b/emath/src/rot2.rs @@ -20,6 +20,7 @@ use super::Vec2; pub struct Rot2 { /// angle.sin() s: f32, + /// angle.cos() c: f32, } @@ -93,6 +94,7 @@ impl std::fmt::Debug for Rot2 { impl std::ops::Mul for Rot2 { type Output = Rot2; + fn mul(self, r: Rot2) -> Rot2 { /* |lc -ls| * |rc -rs| @@ -108,6 +110,7 @@ impl std::ops::Mul for Rot2 { /// Rotates (and maybe scales) the vector. impl std::ops::Mul for Rot2 { type Output = Vec2; + fn mul(self, v: Vec2) -> Vec2 { Vec2 { x: self.c * v.x - self.s * v.y, @@ -119,6 +122,7 @@ impl std::ops::Mul for Rot2 { /// Scales the rotor. impl std::ops::Mul for f32 { type Output = Rot2; + fn mul(self, r: Rot2) -> Rot2 { Rot2 { c: self * r.c, @@ -130,6 +134,7 @@ impl std::ops::Mul for f32 { /// Scales the rotor. impl std::ops::Mul for Rot2 { type Output = Rot2; + fn mul(self, r: f32) -> Rot2 { Rot2 { c: self.c * r, @@ -141,6 +146,7 @@ impl std::ops::Mul for Rot2 { /// Scales the rotor. impl std::ops::Div for Rot2 { type Output = Rot2; + fn div(self, r: f32) -> Rot2 { Rot2 { c: self.c / r, diff --git a/emath/src/vec2.rs b/emath/src/vec2.rs index d2f08b05..ac70f9b4 100644 --- a/emath/src/vec2.rs +++ b/emath/src/vec2.rs @@ -13,6 +13,7 @@ use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign}; pub struct Vec2 { /// Rightwards. Width. pub x: f32, + /// Downwards. Height. pub y: f32, } diff --git a/epaint/src/bezier.rs b/epaint/src/bezier.rs index 26f31fee..0f520f79 100644 --- a/epaint/src/bezier.rs +++ b/epaint/src/bezier.rs @@ -852,6 +852,7 @@ mod tests { assert_eq!(result.len(), 240); } + #[test] fn test_cubic_bounding_box() { let curve = CubicBezierShape { @@ -909,6 +910,7 @@ mod tests { assert!((bbox.max.x - 199.27).abs() < 0.01); assert!((bbox.max.y - 170.0).abs() < 0.01); } + #[test] fn test_cubic_different_tolerance_flattening() { let curve = CubicBezierShape { diff --git a/epaint/src/color.rs b/epaint/src/color.rs index de29b6a8..a99d03b1 100644 --- a/epaint/src/color.rs +++ b/epaint/src/color.rs @@ -587,10 +587,13 @@ pub fn gamma_from_linear(linear: f32) -> f32 { pub struct Hsva { /// hue 0-1 pub h: f32, + /// saturation 0-1 pub s: f32, + /// value 0-1 pub v: f32, + /// alpha 0-1. A negative value signifies an additive color (and alpha is ignored). pub a: f32, } @@ -727,6 +730,7 @@ impl From for Rgba { Rgba(hsva.to_rgba_premultiplied()) } } + impl From for Hsva { fn from(rgba: Rgba) -> Hsva { Self::from_rgba_premultiplied(rgba.0[0], rgba.0[1], rgba.0[2], rgba.0[3]) @@ -738,6 +742,7 @@ impl From for Color32 { Color32::from(Rgba::from(hsva)) } } + impl From for Hsva { fn from(srgba: Color32) -> Hsva { Hsva::from(Rgba::from(srgba)) @@ -811,10 +816,13 @@ fn test_hsv_roundtrip() { pub struct HsvaGamma { /// hue 0-1 pub h: f32, + /// saturation 0-1 pub s: f32, + /// value 0-1, in gamma-space (~perceptually even) pub v: f32, + /// alpha 0-1. A negative value signifies an additive color (and alpha is ignored). pub a: f32, } diff --git a/epaint/src/image.rs b/epaint/src/image.rs index 7fe1a1ac..fa5d587c 100644 --- a/epaint/src/image.rs +++ b/epaint/src/image.rs @@ -12,6 +12,7 @@ use crate::{textures::TextureFilter, Color32}; pub enum ImageData { /// RGBA image. Color(ColorImage), + /// Used for the font texture. Font(FontImage), } @@ -47,6 +48,7 @@ impl ImageData { pub struct ColorImage { /// width, height. pub size: [usize; 2], + /// The pixels, row by row, from top to bottom. pub pixels: Vec, } diff --git a/epaint/src/lib.rs b/epaint/src/lib.rs index e0ba95cd..794778a2 100644 --- a/epaint/src/lib.rs +++ b/epaint/src/lib.rs @@ -105,6 +105,7 @@ pub struct ClippedPrimitive { /// Clip / scissor rectangle. /// Only show the part of the [`Mesh`] that falls within this. pub clip_rect: emath::Rect, + /// What to paint - either a [`Mesh`] or a [`PaintCallback`]. pub primitive: Primitive, } diff --git a/epaint/src/shape.rs b/epaint/src/shape.rs index fae70cb8..9bf4e32a 100644 --- a/epaint/src/shape.rs +++ b/epaint/src/shape.rs @@ -18,22 +18,36 @@ pub use crate::{CubicBezierShape, QuadraticBezierShape}; pub enum Shape { /// Paint nothing. This can be useful as a placeholder. Noop, + /// Recursively nest more shapes - sometimes a convenience to be able to do. /// For performance reasons it is better to avoid it. Vec(Vec), + + /// Circle with optional outline and fill. Circle(CircleShape), + /// A line between two points. - LineSegment { - points: [Pos2; 2], - stroke: Stroke, - }, + LineSegment { points: [Pos2; 2], stroke: Stroke }, + /// A series of lines between points. /// The path can have a stroke and/or fill (if closed). Path(PathShape), + + /// Rectangle with optional outline and fill. Rect(RectShape), + + /// Text. Text(TextShape), + + /// A general triangle mesh. + /// + /// Can be used to display images. Mesh(Mesh), + + /// A quadratic [Bézier Curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve). QuadraticBezier(QuadraticBezierShape), + + /// A cubic [Bézier Curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve). CubicBezier(CubicBezierShape), /// Backend-specific painting. @@ -369,11 +383,15 @@ impl From for Shape { pub struct PathShape { /// Filled paths should prefer clockwise order. pub points: Vec, + /// If true, connect the first and last of the points together. /// This is required if `fill != TRANSPARENT`. pub closed: bool, + /// Fill is only supported for convex polygons. pub fill: Color32, + + /// Color and thickness of the line. pub stroke: Stroke, } @@ -444,9 +462,14 @@ impl From for Shape { #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct RectShape { pub rect: Rect, + /// How rounded the corners are. Use `Rounding::none()` for no rounding. pub rounding: Rounding, + + /// How to fill the rectangle. pub fill: Color32, + + /// The thickness and color of the outline. pub stroke: Stroke, } @@ -499,10 +522,13 @@ impl From for Shape { pub struct Rounding { /// Radius of the rounding of the North-West (left top) corner. pub nw: f32, + /// Radius of the rounding of the North-East (right top) corner. pub ne: f32, + /// Radius of the rounding of the South-West (left bottom) corner. pub sw: f32, + /// Radius of the rounding of the South-East (right bottom) corner. pub se: f32, } diff --git a/epaint/src/stats.rs b/epaint/src/stats.rs index 47f3e905..5abbe456 100644 --- a/epaint/src/stats.rs +++ b/epaint/src/stats.rs @@ -33,6 +33,7 @@ impl From<&[T]> for AllocInfo { impl std::ops::Add for AllocInfo { type Output = AllocInfo; + fn add(self, rhs: AllocInfo) -> AllocInfo { use ElementSize::{Heterogenous, Homogeneous, Unknown}; let element_size = match (self.element_size, rhs.element_size) { @@ -113,9 +114,11 @@ impl AllocInfo { assert!(self.element_size != ElementSize::Heterogenous); self.num_elements } + pub fn num_allocs(&self) -> usize { self.num_allocs } + pub fn num_bytes(&self) -> usize { self.num_bytes } diff --git a/epaint/src/text/cursor.rs b/epaint/src/text/cursor.rs index 9967853c..b2078739 100644 --- a/epaint/src/text/cursor.rs +++ b/epaint/src/text/cursor.rs @@ -33,6 +33,7 @@ impl PartialEq for CCursor { impl std::ops::Add for CCursor { type Output = CCursor; + fn add(self, rhs: usize) -> Self::Output { CCursor { index: self.index.saturating_add(rhs), @@ -43,6 +44,7 @@ impl std::ops::Add for CCursor { impl std::ops::Sub for CCursor { type Output = CCursor; + fn sub(self, rhs: usize) -> Self::Output { CCursor { index: self.index.saturating_sub(rhs), diff --git a/epaint/src/text/text_layout.rs b/epaint/src/text/text_layout.rs index c5649dd6..3b222091 100644 --- a/epaint/src/text/text_layout.rs +++ b/epaint/src/text/text_layout.rs @@ -42,7 +42,9 @@ impl PointScale { struct Paragraph { /// Start of the next glyph to be added. pub cursor_x: f32, + pub glyphs: Vec, + /// In case of an empty paragraph ("\n"), use this as height. pub empty_paragraph_height: f32, } @@ -715,16 +717,21 @@ struct RowBreakCandidates { /// Breaking at ` ` or other whitespace /// is always the primary candidate. space: Option, + /// Logograms (single character representing a whole word) are good candidates for line break. logogram: Option, + /// Kana (Japanese hiragana and katakana) may be line broken unless before a gyōtō kinsoku character. kana: Option, + /// Breaking at a dash is a super- /// good idea. dash: Option, + /// This is nicer for things like URLs, e.g. www. /// example.com. punctuation: Option, + /// Breaking after just random character is some /// times necessary. any: Option, diff --git a/epaint/src/text/text_layout_types.rs b/epaint/src/text/text_layout_types.rs index dca1fb10..830acb84 100644 --- a/epaint/src/text/text_layout_types.rs +++ b/epaint/src/text/text_layout_types.rs @@ -395,14 +395,19 @@ impl Default for RowVisuals { #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Glyph { + /// The character this glyph represents. pub chr: char, + /// Relative to the galley position. /// Logical position: pos.y is the same for all chars of the same [`TextFormat`]. pub pos: Pos2, + /// Advance width and font row height. pub size: Vec2, + /// Position of the glyph in the font texture, in texels. pub uv_rect: UvRect, + /// Index into [`LayoutJob::sections`]. Decides color etc. pub section_index: u32, } diff --git a/epaint/src/texture_atlas.rs b/epaint/src/texture_atlas.rs index 9e2983fe..38d70d50 100644 --- a/epaint/src/texture_atlas.rs +++ b/epaint/src/texture_atlas.rs @@ -6,10 +6,13 @@ use crate::{textures::TextureFilter, FontImage, ImageDelta}; struct Rectu { /// inclusive min_x: usize, + /// inclusive min_y: usize, + /// exclusive max_x: usize, + /// exclusive max_y: usize, } @@ -55,11 +58,13 @@ pub struct PreparedDisc { #[derive(Clone)] pub struct TextureAtlas { image: FontImage, + /// What part of the image that is dirty dirty: Rectu, /// Used for when allocating new rectangles. cursor: (usize, usize), + row_height: usize, /// Set when someone requested more space than was available. diff --git a/epaint/src/util/ordered_float.rs b/epaint/src/util/ordered_float.rs index 8bbcef22..1bef308c 100644 --- a/epaint/src/util/ordered_float.rs +++ b/epaint/src/util/ordered_float.rs @@ -89,7 +89,9 @@ impl FloatOrd for f64 { /// Internal abstraction over floating point types #[doc(hidden)] pub trait Float: PartialOrd + PartialEq + private::FloatImpl {} + impl Float for f32 {} + impl Float for f64 {} // Keep this trait in private module, to avoid exposing its methods as extensions in user code @@ -98,6 +100,7 @@ mod private { pub trait FloatImpl { fn is_nan(&self) -> bool; + fn hash(&self, state: &mut H); }