Move egui/math into new crate emath
This commit is contained in:
parent
aee1474b6e
commit
a0b0f36d29
38 changed files with 187 additions and 97 deletions
|
@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
* Center window titles.
|
* Center window titles.
|
||||||
* Tweak size and alignment of some emojis to match other text.
|
* Tweak size and alignment of some emojis to match other text.
|
||||||
|
* Rename feature "serde" to "persistence".
|
||||||
|
|
||||||
### Fixed 🐛
|
### Fixed 🐛
|
||||||
|
|
||||||
|
|
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -642,6 +642,7 @@ version = "0.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"atomic_refcell",
|
"atomic_refcell",
|
||||||
|
"emath",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rusttype",
|
"rusttype",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -703,6 +704,13 @@ version = "1.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "emath"
|
||||||
|
version = "0.7.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "epi"
|
name = "epi"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
|
|
@ -5,6 +5,7 @@ members = [
|
||||||
"egui_glium",
|
"egui_glium",
|
||||||
"egui_web",
|
"egui_web",
|
||||||
"egui",
|
"egui",
|
||||||
|
"emath",
|
||||||
"epi",
|
"epi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ include = [
|
||||||
[lib]
|
[lib]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
emath = { path = "../emath" }
|
||||||
|
|
||||||
ahash = { version = "0.6", features = ["std"], default-features = false }
|
ahash = { version = "0.6", features = ["std"], default-features = false }
|
||||||
atomic_refcell = { version = "0.1", optional = true } # Used instead of parking_lot when you are always using Egui in a single thread. About as fast as parking_lot. Panics on multi-threaded use of egui::Context.
|
atomic_refcell = { version = "0.1", optional = true } # Used instead of parking_lot when you are always using Egui in a single thread. About as fast as parking_lot. Panics on multi-threaded use of egui::Context.
|
||||||
parking_lot = { version = "0.11", optional = true } # Using parking_lot over std::sync::Mutex gives 50% speedups in some real-world scenarios
|
parking_lot = { version = "0.11", optional = true } # Using parking_lot over std::sync::Mutex gives 50% speedups in some real-world scenarios
|
||||||
|
@ -27,6 +29,7 @@ serde = { version = "1", features = ["derive", "rc"], optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["atomic_refcell", "default_fonts"]
|
default = ["atomic_refcell", "default_fonts"]
|
||||||
|
persistence = ["serde", "emath/serde"]
|
||||||
|
|
||||||
# If set, egui will use `include_bytes!` to bundle some fonts.
|
# If set, egui will use `include_bytes!` to bundle some fonts.
|
||||||
# If you plan on specifying your own fonts you may disable this feature.
|
# If you plan on specifying your own fonts you may disable this feature.
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::*;
|
||||||
|
|
||||||
/// State that is persisted between frames
|
/// State that is persisted between frames
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
/// Last known pos
|
/// Last known pos
|
||||||
pub pos: Pos2,
|
pub pos: Pos2,
|
||||||
|
|
|
@ -7,8 +7,8 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
open: bool,
|
open: bool,
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ pub(crate) fn paint_icon(ui: &mut Ui, openness: f32, response: &Response) {
|
||||||
let rect = Rect::from_center_size(rect.center(), vec2(rect.width(), rect.height()) * 0.75);
|
let rect = Rect::from_center_size(rect.center(), vec2(rect.width(), rect.height()) * 0.75);
|
||||||
let mut points = vec![rect.left_top(), rect.right_top(), rect.center_bottom()];
|
let mut points = vec![rect.left_top(), rect.right_top(), rect.center_bottom()];
|
||||||
use std::f32::consts::TAU;
|
use std::f32::consts::TAU;
|
||||||
let rotation = Rot2::from_angle(remap(openness, 0.0..=1.0, -TAU / 4.0..=0.0));
|
let rotation = math::Rot2::from_angle(remap(openness, 0.0..=1.0, -TAU / 4.0..=0.0));
|
||||||
for p in &mut points {
|
for p in &mut points {
|
||||||
*p = rect.center() + rotation * (*p - rect.center());
|
*p = rect.center() + rotation * (*p - rect.center());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
/// This is the size that the user has picked by dragging the resize handles.
|
/// This is the size that the user has picked by dragging the resize handles.
|
||||||
/// This may be smaller and/or larger than the actual size.
|
/// This may be smaller and/or larger than the actual size.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
/// Positive offset means scrolling down/right
|
/// Positive offset means scrolling down/right
|
||||||
offset: Vec2,
|
offset: Vec2,
|
||||||
|
@ -10,7 +10,7 @@ pub(crate) struct State {
|
||||||
show_scroll: bool,
|
show_scroll: bool,
|
||||||
|
|
||||||
/// Momentum, used for kinetic scrolling
|
/// Momentum, used for kinetic scrolling
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub vel: Vec2,
|
pub vel: Vec2,
|
||||||
/// Mouse offset relative to the top of the handle when started moving the handle.
|
/// Mouse offset relative to the top of the handle when started moving the handle.
|
||||||
scroll_start_offset_from_top: Option<f32>,
|
scroll_start_offset_from_top: Option<f32>,
|
||||||
|
@ -177,7 +177,7 @@ impl Prepared {
|
||||||
// We take the scroll target so only this ScrollArea will use it.
|
// We take the scroll target so only this ScrollArea will use it.
|
||||||
let scroll_target = content_ui.ctx().frame_state().scroll_target.take();
|
let scroll_target = content_ui.ctx().frame_state().scroll_target.take();
|
||||||
if let Some((scroll_y, align)) = scroll_target {
|
if let Some((scroll_y, align)) = scroll_target {
|
||||||
let center_factor = align.scroll_center_factor();
|
let center_factor = align.to_factor();
|
||||||
|
|
||||||
let top = content_ui.min_rect().top();
|
let top = content_ui.min_rect().top();
|
||||||
let visible_range = top..=top + content_ui.clip_rect().height();
|
let visible_range = top..=top + content_ui.clip_rect().height();
|
||||||
|
|
|
@ -720,7 +720,7 @@ impl TitleBar {
|
||||||
self.title_label = self.title_label.text_color(style.fg_stroke.color);
|
self.title_label = self.title_label.text_color(style.fg_stroke.color);
|
||||||
|
|
||||||
let full_top_rect = Rect::from_x_y_ranges(self.rect.x_range(), self.min_rect.y_range());
|
let full_top_rect = Rect::from_x_y_ranges(self.rect.x_range(), self.min_rect.y_range());
|
||||||
let text_pos = align::center_size_in_rect(self.title_galley.size, full_top_rect);
|
let text_pos = math::align::center_size_in_rect(self.title_galley.size, full_top_rect);
|
||||||
let text_pos = text_pos.left_top() - 2.0 * Vec2::Y; // HACK: center on x-height of text (looks better)
|
let text_pos = text_pos.left_top() - 2.0 * Vec2::Y; // HACK: center on x-height of text (looks better)
|
||||||
self.title_label
|
self.title_label
|
||||||
.paint_galley(ui, text_pos, self.title_galley);
|
.paint_galley(ui, text_pos, self.title_galley);
|
||||||
|
|
|
@ -28,7 +28,7 @@ use std::hash::Hash;
|
||||||
/// Then there are widgets that need no identifiers at all, like labels,
|
/// Then there are widgets that need no identifiers at all, like labels,
|
||||||
/// because they have no state nor are interacted with.
|
/// because they have no state nor are interacted with.
|
||||||
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
|
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Id(u64);
|
pub struct Id(u64);
|
||||||
|
|
||||||
impl Id {
|
impl Id {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//! uis for egui types.
|
//! uis for egui types.
|
||||||
use crate::{
|
use crate::{
|
||||||
math::*,
|
|
||||||
paint::{self, PaintCmd, Texture, Triangles},
|
paint::{self, PaintCmd, Texture, Triangles},
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{math::Rect, paint::PaintCmd, Id, *};
|
||||||
|
|
||||||
/// Different layer categories
|
/// Different layer categories
|
||||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub enum Order {
|
pub enum Order {
|
||||||
/// Painted behind all floating windows
|
/// Painted behind all floating windows
|
||||||
Background,
|
Background,
|
||||||
|
@ -40,7 +40,7 @@ impl Order {
|
||||||
/// An identifier for a paint layer.
|
/// An identifier for a paint layer.
|
||||||
/// Also acts as an identifier for [`Area`]:s.
|
/// Also acts as an identifier for [`Area`]:s.
|
||||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct LayerId {
|
pub struct LayerId {
|
||||||
pub order: Order,
|
pub order: Order,
|
||||||
pub id: Id,
|
pub id: Id,
|
||||||
|
|
|
@ -66,8 +66,8 @@ impl Region {
|
||||||
|
|
||||||
/// Layout direction, one of `LeftToRight`, `RightToLeft`, `TopDown`, `BottomUp`.
|
/// Layout direction, one of `LeftToRight`, `RightToLeft`, `TopDown`, `BottomUp`.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
#[cfg_attr(feature = "persistence", serde(rename_all = "snake_case"))]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
LeftToRight,
|
LeftToRight,
|
||||||
RightToLeft,
|
RightToLeft,
|
||||||
|
@ -95,7 +95,7 @@ impl Direction {
|
||||||
|
|
||||||
/// The layout of a [`Ui`][`crate::Ui`], e.g. "vertical & centered".
|
/// The layout of a [`Ui`][`crate::Ui`], e.g. "vertical & centered".
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
// #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
// #[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
/// Main axis direction
|
/// Main axis direction
|
||||||
main_dir: Direction,
|
main_dir: Direction,
|
||||||
|
|
|
@ -86,7 +86,6 @@ mod input;
|
||||||
mod introspection;
|
mod introspection;
|
||||||
mod layers;
|
mod layers;
|
||||||
mod layout;
|
mod layout;
|
||||||
pub mod math;
|
|
||||||
mod memory;
|
mod memory;
|
||||||
pub mod menu;
|
pub mod menu;
|
||||||
pub mod paint;
|
pub mod paint;
|
||||||
|
@ -97,6 +96,8 @@ mod ui;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod widgets;
|
pub mod widgets;
|
||||||
|
|
||||||
|
pub use emath as math;
|
||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
containers::*,
|
containers::*,
|
||||||
context::{Context, CtxRef},
|
context::{Context, CtxRef},
|
||||||
|
@ -104,7 +105,7 @@ pub use {
|
||||||
input::*,
|
input::*,
|
||||||
layers::*,
|
layers::*,
|
||||||
layout::*,
|
layout::*,
|
||||||
math::*,
|
math::{clamp, lerp, pos2, remap, remap_clamp, vec2, Align, Align2, NumExt, Pos2, Rect, Vec2},
|
||||||
memory::Memory,
|
memory::Memory,
|
||||||
paint::{
|
paint::{
|
||||||
color, Color32, FontDefinitions, FontFamily, PaintCmd, PaintJobs, Rgba, Stroke, TextStyle,
|
color, Color32, FontDefinitions, FontFamily, PaintCmd, PaintJobs, Rgba, Stroke, TextStyle,
|
||||||
|
|
|
@ -18,50 +18,50 @@ use crate::{
|
||||||
///
|
///
|
||||||
/// If you want this to persist when closing your app you should serialize `Memory` and store it.
|
/// If you want this to persist when closing your app you should serialize `Memory` and store it.
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
pub(crate) options: Options,
|
pub(crate) options: Options,
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) interaction: Interaction,
|
pub(crate) interaction: Interaction,
|
||||||
|
|
||||||
// states of various types of widgets
|
// states of various types of widgets
|
||||||
pub(crate) collapsing_headers: HashMap<Id, collapsing_header::State>,
|
pub(crate) collapsing_headers: HashMap<Id, collapsing_header::State>,
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) menu_bar: HashMap<Id, menu::BarState>,
|
pub(crate) menu_bar: HashMap<Id, menu::BarState>,
|
||||||
pub(crate) resize: HashMap<Id, resize::State>,
|
pub(crate) resize: HashMap<Id, resize::State>,
|
||||||
pub(crate) scroll_areas: HashMap<Id, scroll_area::State>,
|
pub(crate) scroll_areas: HashMap<Id, scroll_area::State>,
|
||||||
pub(crate) text_edit: HashMap<Id, text_edit::State>,
|
pub(crate) text_edit: HashMap<Id, text_edit::State>,
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) window_interaction: Option<window::WindowInteraction>,
|
pub(crate) window_interaction: Option<window::WindowInteraction>,
|
||||||
|
|
||||||
/// For temporary edit of e.g. a slider value.
|
/// For temporary edit of e.g. a slider value.
|
||||||
/// Couples with [`Interaction::kb_focus_id`].
|
/// Couples with [`Interaction::kb_focus_id`].
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) temp_edit_string: Option<String>,
|
pub(crate) temp_edit_string: Option<String>,
|
||||||
|
|
||||||
pub(crate) areas: Areas,
|
pub(crate) areas: Areas,
|
||||||
|
|
||||||
/// Used by color picker
|
/// Used by color picker
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) color_cache: Cache<Color32, Hsva>,
|
pub(crate) color_cache: Cache<Color32, Hsva>,
|
||||||
|
|
||||||
/// Which popup-window is open (if any)?
|
/// Which popup-window is open (if any)?
|
||||||
/// Could be a combo box, color picker, menu etc.
|
/// Could be a combo box, color picker, menu etc.
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
popup: Option<Id>,
|
popup: Option<Id>,
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
everything_is_visible: bool,
|
everything_is_visible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub(crate) struct Options {
|
pub(crate) struct Options {
|
||||||
/// The default style for new `Ui`:s.
|
/// The default style for new `Ui`:s.
|
||||||
pub(crate) style: std::sync::Arc<Style>,
|
pub(crate) style: std::sync::Arc<Style>,
|
||||||
|
@ -304,8 +304,8 @@ impl Memory {
|
||||||
/// Keeps track of `Area`s, which are free-floating `Ui`s.
|
/// Keeps track of `Area`s, which are free-floating `Ui`s.
|
||||||
/// These `Area`s can be in any `Order`.
|
/// These `Area`s can be in any `Order`.
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct Areas {
|
pub struct Areas {
|
||||||
areas: HashMap<Id, area::State>,
|
areas: HashMap<Id, area::State>,
|
||||||
/// Top is last
|
/// Top is last
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::math::clamp;
|
||||||
/// Internally this uses 0-255 gamma space `sRGBA` color with premultiplied alpha.
|
/// Internally this uses 0-255 gamma space `sRGBA` color with premultiplied alpha.
|
||||||
/// Alpha channel is in linear space.
|
/// Alpha channel is in linear space.
|
||||||
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Color32(pub(crate) [u8; 4]);
|
pub struct Color32(pub(crate) [u8; 4]);
|
||||||
|
|
||||||
impl std::ops::Index<usize> for Color32 {
|
impl std::ops::Index<usize> for Color32 {
|
||||||
|
@ -130,7 +130,7 @@ impl Color32 {
|
||||||
|
|
||||||
/// 0-1 linear space `RGBA` color with premultiplied alpha.
|
/// 0-1 linear space `RGBA` color with premultiplied alpha.
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Rgba(pub(crate) [f32; 4]);
|
pub struct Rgba(pub(crate) [f32; 4]);
|
||||||
|
|
||||||
impl std::ops::Index<usize> for Rgba {
|
impl std::ops::Index<usize> for Rgba {
|
||||||
|
|
|
@ -192,7 +192,7 @@ impl PaintCmd {
|
||||||
|
|
||||||
/// Describes the width and color of a line.
|
/// Describes the width and color of a line.
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Stroke {
|
pub struct Stroke {
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
pub color: Color32,
|
pub color: Color32,
|
||||||
|
|
|
@ -14,8 +14,8 @@ use super::{
|
||||||
// TODO: rename
|
// TODO: rename
|
||||||
/// One of a few categories of styles of text, e.g. body, button or heading.
|
/// One of a few categories of styles of text, e.g. body, button or heading.
|
||||||
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
#[cfg_attr(feature = "persistence", serde(rename_all = "snake_case"))]
|
||||||
pub enum TextStyle {
|
pub enum TextStyle {
|
||||||
/// Used when small text is needed.
|
/// Used when small text is needed.
|
||||||
Small,
|
Small,
|
||||||
|
@ -45,8 +45,8 @@ impl TextStyle {
|
||||||
|
|
||||||
/// Which style of font: [`Monospace`][`FontFamily::Monospace`] or [`Proportional`][`FontFamily::Proportional`].
|
/// Which style of font: [`Monospace`][`FontFamily::Monospace`] or [`Proportional`][`FontFamily::Proportional`].
|
||||||
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
#[cfg_attr(feature = "persistence", serde(rename_all = "snake_case"))]
|
||||||
pub enum FontFamily {
|
pub enum FontFamily {
|
||||||
/// A font where each character is the same width (`w` is the same width as `i`).
|
/// A font where each character is the same width (`w` is the same width as `i`).
|
||||||
Monospace,
|
Monospace,
|
||||||
|
@ -81,15 +81,15 @@ fn rusttype_font_from_font_data(name: &str, data: &FontData) -> rusttype::Font<'
|
||||||
/// ctx.set_fonts(fonts);
|
/// ctx.set_fonts(fonts);
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct FontDefinitions {
|
pub struct FontDefinitions {
|
||||||
/// List of font names and their definitions.
|
/// List of font names and their definitions.
|
||||||
/// The definition must be the contents of either a `.ttf` or `.otf` font file.
|
/// The definition must be the contents of either a `.ttf` or `.otf` font file.
|
||||||
///
|
///
|
||||||
/// Egui has built-in-default for these,
|
/// Egui has built-in-default for these,
|
||||||
/// but you can override them if you like.
|
/// but you can override them if you like.
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub font_data: BTreeMap<String, FontData>,
|
pub font_data: BTreeMap<String, FontData>,
|
||||||
|
|
||||||
/// Which fonts (names) to use for each [`FontFamily`].
|
/// Which fonts (names) to use for each [`FontFamily`].
|
||||||
|
|
|
@ -20,7 +20,7 @@ use crate::math::{pos2, NumExt, Rect, Vec2};
|
||||||
|
|
||||||
/// Character cursor
|
/// Character cursor
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct CCursor {
|
pub struct CCursor {
|
||||||
/// Character offset (NOT byte offset!).
|
/// Character offset (NOT byte offset!).
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
|
@ -71,7 +71,7 @@ impl std::ops::Sub<usize> for CCursor {
|
||||||
|
|
||||||
/// Row Cursor
|
/// Row Cursor
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct RCursor {
|
pub struct RCursor {
|
||||||
/// 0 is first row, and so on.
|
/// 0 is first row, and so on.
|
||||||
/// Note that a single paragraph can span multiple rows.
|
/// Note that a single paragraph can span multiple rows.
|
||||||
|
@ -86,7 +86,7 @@ pub struct RCursor {
|
||||||
|
|
||||||
/// Paragraph Cursor
|
/// Paragraph Cursor
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct PCursor {
|
pub struct PCursor {
|
||||||
/// 0 is first paragraph, and so on.
|
/// 0 is first paragraph, and so on.
|
||||||
/// Note that a single paragraph can span multiple rows.
|
/// Note that a single paragraph can span multiple rows.
|
||||||
|
@ -118,7 +118,7 @@ impl PartialEq for PCursor {
|
||||||
/// pcursor/rcursor can also point to after the end of the paragraph/row.
|
/// pcursor/rcursor can also point to after the end of the paragraph/row.
|
||||||
/// Does not implement `PartialEq` because you must think which cursor should be equivalent.
|
/// Does not implement `PartialEq` because you must think which cursor should be equivalent.
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Cursor {
|
pub struct Cursor {
|
||||||
pub ccursor: CCursor,
|
pub ccursor: CCursor,
|
||||||
pub rcursor: RCursor,
|
pub rcursor: RCursor,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Shadow {
|
pub struct Shadow {
|
||||||
// The shadow extends this much outside the rect.
|
// The shadow extends this much outside the rect.
|
||||||
pub extrusion: f32,
|
pub extrusion: f32,
|
||||||
|
|
|
@ -446,8 +446,8 @@ use self::PathType::{Closed, Open};
|
||||||
|
|
||||||
/// Tessellation quality options
|
/// Tessellation quality options
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct TessellationOptions {
|
pub struct TessellationOptions {
|
||||||
/// Size of a pixel in points, e.g. 0.5
|
/// Size of a pixel in points, e.g. 0.5
|
||||||
pub aa_size: f32,
|
pub aa_size: f32,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Egui theme (spacing, colors, etc).
|
||||||
|
|
||||||
#![allow(clippy::if_same_then_else)]
|
#![allow(clippy::if_same_then_else)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -9,8 +11,8 @@ use crate::{
|
||||||
|
|
||||||
/// Specifies the look and feel of a [`Ui`].
|
/// Specifies the look and feel of a [`Ui`].
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct Style {
|
pub struct Style {
|
||||||
/// Default `TextStyle` for normal text (i.e. for `Label` and `TextEdit`).
|
/// Default `TextStyle` for normal text (i.e. for `Label` and `TextEdit`).
|
||||||
pub body_text_style: TextStyle,
|
pub body_text_style: TextStyle,
|
||||||
|
@ -39,8 +41,8 @@ impl Style {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct Spacing {
|
pub struct Spacing {
|
||||||
/// Horizontal and vertical spacing between widgets
|
/// Horizontal and vertical spacing between widgets
|
||||||
pub item_spacing: Vec2,
|
pub item_spacing: Vec2,
|
||||||
|
@ -95,8 +97,8 @@ impl Spacing {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct Interaction {
|
pub struct Interaction {
|
||||||
/// Mouse must be the close to the side of a window to resize
|
/// Mouse must be the close to the side of a window to resize
|
||||||
pub resize_grab_radius_side: f32,
|
pub resize_grab_radius_side: f32,
|
||||||
|
@ -106,8 +108,8 @@ pub struct Interaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct Visuals {
|
pub struct Visuals {
|
||||||
/// Override default text color for all text.
|
/// Override default text color for all text.
|
||||||
///
|
///
|
||||||
|
@ -168,16 +170,16 @@ impl Visuals {
|
||||||
|
|
||||||
/// Selected text, selected elements etc
|
/// Selected text, selected elements etc
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct Selection {
|
pub struct Selection {
|
||||||
pub bg_fill: Color32,
|
pub bg_fill: Color32,
|
||||||
pub stroke: Stroke,
|
pub stroke: Stroke,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub struct Widgets {
|
pub struct Widgets {
|
||||||
/// For an interactive widget that is being interacted with
|
/// For an interactive widget that is being interacted with
|
||||||
pub active: WidgetVisuals,
|
pub active: WidgetVisuals,
|
||||||
|
@ -207,7 +209,7 @@ impl Widgets {
|
||||||
|
|
||||||
/// bg = background, fg = foreground.
|
/// bg = background, fg = foreground.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct WidgetVisuals {
|
pub struct WidgetVisuals {
|
||||||
/// Background color of widget
|
/// Background color of widget
|
||||||
pub bg_fill: Color32,
|
pub bg_fill: Color32,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{lerp, math::Rect, Align, CtxRef, Id, LayerId, Ui};
|
||||||
/// What Egui emits each frame.
|
/// What Egui emits each frame.
|
||||||
/// The backend should use this.
|
/// The backend should use this.
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
// #[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
// #[cfg_attr(feature = "persistence", derive(serde::Serialize))]
|
||||||
pub struct Output {
|
pub struct Output {
|
||||||
/// Set the cursor to this icon.
|
/// Set the cursor to this icon.
|
||||||
pub cursor_icon: CursorIcon,
|
pub cursor_icon: CursorIcon,
|
||||||
|
@ -26,8 +26,8 @@ pub struct Output {
|
||||||
///
|
///
|
||||||
/// Egui emits a `CursorIcond` in [`Output`] each frame as a request to the integration.
|
/// Egui emits a `CursorIcond` in [`Output`] each frame as a request to the integration.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
// #[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
// #[cfg_attr(feature = "persistence", derive(serde::Serialize))]
|
||||||
// #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
// #[cfg_attr(feature = "persistence", serde(rename_all = "snake_case"))]
|
||||||
pub enum CursorIcon {
|
pub enum CursorIcon {
|
||||||
Default,
|
Default,
|
||||||
/// Pointing hand, used for e.g. web links
|
/// Pointing hand, used for e.g. web links
|
||||||
|
@ -187,7 +187,7 @@ impl Response {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn scroll_to_me(&self, align: Align) {
|
pub fn scroll_to_me(&self, align: Align) {
|
||||||
let scroll_target = lerp(self.rect.y_range(), align.scroll_center_factor());
|
let scroll_target = lerp(self.rect.y_range(), align.to_factor());
|
||||||
self.ctx.frame_state().scroll_target = Some((scroll_target, align));
|
self.ctx.frame_state().scroll_target = Some((scroll_target, align));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ impl std::ops::BitOrAssign for Response {
|
||||||
|
|
||||||
/// What sort of interaction is a widget sensitive to?
|
/// What sort of interaction is a widget sensitive to?
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
// #[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
// #[cfg_attr(feature = "persistence", derive(serde::Serialize))]
|
||||||
pub struct Sense {
|
pub struct Sense {
|
||||||
/// buttons, sliders, windows ...
|
/// buttons, sliders, windows ...
|
||||||
pub click: bool,
|
pub click: bool,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
/// Maximum number of undos.
|
/// Maximum number of undos.
|
||||||
/// If your state is resource intensive, you should keep this low.
|
/// If your state is resource intensive, you should keep this low.
|
||||||
|
@ -48,7 +48,7 @@ impl Default for Settings {
|
||||||
/// Rule 1) will make sure an undo point is not created until you _stop_ dragging that slider.
|
/// Rule 1) will make sure an undo point is not created until you _stop_ dragging that slider.
|
||||||
/// Rule 2) will make sure that you will get some undo points even if you are constantly changing the state.
|
/// Rule 2) will make sure that you will get some undo points even if you are constantly changing the state.
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Undoer<State> {
|
pub struct Undoer<State> {
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ pub struct Undoer<State> {
|
||||||
/// The latest undo point may (often) be the current state.
|
/// The latest undo point may (often) be the current state.
|
||||||
undos: VecDeque<State>,
|
undos: VecDeque<State>,
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
flux: Option<Flux<State>>,
|
flux: Option<Flux<State>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ impl<'a> Widget for DragValue<'a> {
|
||||||
let auto_decimals = (aim_rad / speed.abs()).log10().ceil().at_least(0.0) as usize;
|
let auto_decimals = (aim_rad / speed.abs()).log10().ceil().at_least(0.0) as usize;
|
||||||
let max_decimals = max_decimals.unwrap_or(auto_decimals + 2);
|
let max_decimals = max_decimals.unwrap_or(auto_decimals + 2);
|
||||||
let auto_decimals = clamp(auto_decimals, min_decimals..=max_decimals);
|
let auto_decimals = clamp(auto_decimals, min_decimals..=max_decimals);
|
||||||
let value_text = format_with_decimals_in_range(value, auto_decimals..=max_decimals);
|
let value_text = math::format_with_decimals_in_range(value, auto_decimals..=max_decimals);
|
||||||
|
|
||||||
let kb_edit_id = ui.auto_id_with("edit");
|
let kb_edit_id = ui.auto_id_with("edit");
|
||||||
let is_kb_editing = ui.memory().has_kb_focus(kb_edit_id);
|
let is_kb_editing = ui.memory().has_kb_focus(kb_edit_id);
|
||||||
|
@ -193,7 +193,7 @@ impl<'a> Widget for DragValue<'a> {
|
||||||
let delta_value = speed * delta_points;
|
let delta_value = speed * delta_points;
|
||||||
if delta_value != 0.0 {
|
if delta_value != 0.0 {
|
||||||
let new_value = value + delta_value as f64;
|
let new_value = value + delta_value as f64;
|
||||||
let new_value = round_to_decimals(new_value, auto_decimals);
|
let new_value = math::round_to_decimals(new_value, auto_decimals);
|
||||||
let new_value = clamp(new_value, range);
|
let new_value = clamp(new_value, range);
|
||||||
set(&mut value_function, new_value);
|
set(&mut value_function, new_value);
|
||||||
// TODO: To make use or `smart_aim` for `DragValue` we need to store some state somewhere,
|
// TODO: To make use or `smart_aim` for `DragValue` we need to store some state somewhere,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
use crate::{math::NumExt, paint::*, widgets::Label, *};
|
use crate::{paint::*, widgets::Label, *};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ impl<'a> Slider<'a> {
|
||||||
|
|
||||||
fn set_value(&mut self, mut value: f64) {
|
fn set_value(&mut self, mut value: f64) {
|
||||||
if let Some(max_decimals) = self.max_decimals {
|
if let Some(max_decimals) = self.max_decimals {
|
||||||
value = round_to_decimals(value, max_decimals);
|
value = math::round_to_decimals(value, max_decimals);
|
||||||
}
|
}
|
||||||
set(&mut self.get_set_value, value);
|
set(&mut self.get_set_value, value);
|
||||||
}
|
}
|
||||||
|
@ -366,13 +366,13 @@ impl<'a> Slider<'a> {
|
||||||
let auto_decimals = clamp(auto_decimals, min_decimals..=max_decimals);
|
let auto_decimals = clamp(auto_decimals, min_decimals..=max_decimals);
|
||||||
|
|
||||||
if min_decimals == max_decimals {
|
if min_decimals == max_decimals {
|
||||||
format_with_minimum_decimals(value, max_decimals)
|
math::format_with_minimum_decimals(value, max_decimals)
|
||||||
} else if value == 0.0 {
|
} else if value == 0.0 {
|
||||||
"0".to_owned()
|
"0".to_owned()
|
||||||
} else if range == 0.0 {
|
} else if range == 0.0 {
|
||||||
value.to_string()
|
value.to_string()
|
||||||
} else {
|
} else {
|
||||||
format_with_decimals_in_range(value, auto_decimals..=max_decimals)
|
math::format_with_decimals_in_range(value, auto_decimals..=max_decimals)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use crate::{paint::*, util::undoer::Undoer, *};
|
use crate::{paint::*, util::undoer::Undoer, *};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "persistence", serde(default))]
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
cursorp: Option<CursorPair>,
|
cursorp: Option<CursorPair>,
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
undoer: Undoer<(CCursorPair, String)>,
|
undoer: Undoer<(CCursorPair, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
struct CursorPair {
|
struct CursorPair {
|
||||||
/// When selecting with a mouse, this is where the mouse was released.
|
/// When selecting with a mouse, this is where the mouse was released.
|
||||||
/// When moving with e.g. shift+arrows, this is what moves.
|
/// When moving with e.g. shift+arrows, this is what moves.
|
||||||
|
@ -75,7 +75,7 @@ impl CursorPair {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
struct CCursorPair {
|
struct CCursorPair {
|
||||||
/// When selecting with a mouse, this is where the mouse was released.
|
/// When selecting with a mouse, this is where the mouse was released.
|
||||||
/// When moving with e.g. shift+arrows, this is what moves.
|
/// When moving with e.g. shift+arrows, this is what moves.
|
||||||
|
|
|
@ -144,8 +144,8 @@ impl FractalClock {
|
||||||
];
|
];
|
||||||
|
|
||||||
let hand_rotors = [
|
let hand_rotors = [
|
||||||
hands[0].length * Rot2::from_angle(hand_rotations[0]),
|
hands[0].length * math::Rot2::from_angle(hand_rotations[0]),
|
||||||
hands[1].length * Rot2::from_angle(hand_rotations[1]),
|
hands[1].length * math::Rot2::from_angle(hand_rotations[1]),
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
|
|
@ -35,7 +35,7 @@ default = []
|
||||||
http = ["ureq"]
|
http = ["ureq"]
|
||||||
persistence = [
|
persistence = [
|
||||||
"directories-next",
|
"directories-next",
|
||||||
"egui/serde",
|
"egui/persistence",
|
||||||
"epi/serde_json",
|
"epi/serde_json",
|
||||||
"epi/serde",
|
"epi/serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
24
emath/Cargo.toml
Normal file
24
emath/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[package]
|
||||||
|
name = "emath"
|
||||||
|
version = "0.7.0"
|
||||||
|
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||||
|
description = "Minimal 2D math library for GUI work"
|
||||||
|
edition = "2018"
|
||||||
|
homepage = "https://github.com/emilk/egui"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
repository = "https://github.com/emilk/egui"
|
||||||
|
categories = ["gui", "math"]
|
||||||
|
keywords = ["gui", "math"]
|
||||||
|
include = [
|
||||||
|
"**/*.rs",
|
||||||
|
"Cargo.toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1", features = ["derive"], optional = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
5
emath/README.md
Normal file
5
emath/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# emath - Egui Math Library
|
||||||
|
|
||||||
|
A bare-bones 2D math library with types and functions useful for GUI building.
|
||||||
|
|
||||||
|
Made for [`egui`](https://github.com/emilk/egui/).
|
|
@ -1,6 +1,6 @@
|
||||||
//! One- and two-dimensional alignment ([`Align::Center`], [`LEFT_TOP`] etc).
|
//! One- and two-dimensional alignment ([`Align::Center`], [`Align2::LEFT_TOP`] etc).
|
||||||
|
|
||||||
use crate::math::*;
|
use crate::*;
|
||||||
|
|
||||||
/// left/center/right or top/center/bottom alignment for e.g. anchors and `Layout`s.
|
/// left/center/right or top/center/bottom alignment for e.g. anchors and `Layout`s.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
@ -35,7 +35,8 @@ impl Align {
|
||||||
Self::Max
|
Self::Max
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn scroll_center_factor(&self) -> f32 {
|
/// Convert `Min => 0.0`, `Center => 0.5` or `Max => 1.0`.
|
||||||
|
pub fn to_factor(&self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
Self::Min => 0.0,
|
Self::Min => 0.0,
|
||||||
Self::Center => 0.5,
|
Self::Center => 0.5,
|
||||||
|
@ -52,6 +53,7 @@ impl Default for Align {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Two-dimension alignment, e.g. [`Align2::LEFT_TOP`].
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
||||||
|
@ -79,7 +81,7 @@ impl Align2 {
|
||||||
|
|
||||||
/// Used e.g. to anchor a piece of text to a part of the rectangle.
|
/// Used e.g. to anchor a piece of text to a part of the rectangle.
|
||||||
/// Give a position within the rect, specified by the aligns
|
/// Give a position within the rect, specified by the aligns
|
||||||
pub(crate) fn anchor_rect(self, rect: Rect) -> Rect {
|
pub fn anchor_rect(self, rect: Rect) -> Rect {
|
||||||
let x = match self.x() {
|
let x = match self.x() {
|
||||||
Align::Min => rect.left(),
|
Align::Min => rect.left(),
|
||||||
Align::Center => rect.left() - 0.5 * rect.width(),
|
Align::Center => rect.left() - 0.5 * rect.width(),
|
|
@ -1,8 +1,55 @@
|
||||||
//! Vectors, positions, rectangles etc.
|
//! Vectors, positions, rectangles etc.
|
||||||
//!
|
//!
|
||||||
//! Conventions (unless otherwise specified):
|
//! Conventions (unless otherwise specified):
|
||||||
|
//!
|
||||||
//! * All angles are in radians
|
//! * All angles are in radians
|
||||||
//! * All metrics are in points (logical pixels)
|
//! * X+ is right and Y+ is down.
|
||||||
|
//! * (0,0) is left top.
|
||||||
|
//! * Dimension order is always `x y`
|
||||||
|
|
||||||
|
#![cfg_attr(not(debug_assertions), deny(warnings))] // Forbid warnings in release builds
|
||||||
|
#![forbid(unsafe_code)]
|
||||||
|
#![warn(
|
||||||
|
clippy::all,
|
||||||
|
clippy::await_holding_lock,
|
||||||
|
clippy::dbg_macro,
|
||||||
|
clippy::doc_markdown,
|
||||||
|
clippy::empty_enum,
|
||||||
|
clippy::enum_glob_use,
|
||||||
|
clippy::exit,
|
||||||
|
clippy::filter_map_next,
|
||||||
|
clippy::fn_params_excessive_bools,
|
||||||
|
clippy::if_let_mutex,
|
||||||
|
clippy::imprecise_flops,
|
||||||
|
clippy::inefficient_to_string,
|
||||||
|
clippy::linkedlist,
|
||||||
|
clippy::lossy_float_literal,
|
||||||
|
clippy::macro_use_imports,
|
||||||
|
clippy::match_on_vec_items,
|
||||||
|
clippy::match_wildcard_for_single_variants,
|
||||||
|
clippy::mem_forget,
|
||||||
|
clippy::mismatched_target_os,
|
||||||
|
clippy::missing_errors_doc,
|
||||||
|
clippy::missing_safety_doc,
|
||||||
|
clippy::needless_borrow,
|
||||||
|
clippy::needless_continue,
|
||||||
|
clippy::needless_pass_by_value,
|
||||||
|
clippy::option_option,
|
||||||
|
clippy::pub_enum_variant_names,
|
||||||
|
clippy::rest_pat_in_fully_bound_structs,
|
||||||
|
clippy::todo,
|
||||||
|
clippy::unimplemented,
|
||||||
|
clippy::unnested_or_patterns,
|
||||||
|
clippy::verbose_file_reads,
|
||||||
|
future_incompatible,
|
||||||
|
missing_crate_level_docs,
|
||||||
|
missing_doc_code_examples,
|
||||||
|
// missing_docs,
|
||||||
|
nonstandard_style,
|
||||||
|
rust_2018_idioms,
|
||||||
|
unused_doc_comments,
|
||||||
|
)]
|
||||||
|
#![allow(clippy::manual_range_contains)]
|
||||||
|
|
||||||
use std::ops::{Add, Div, Mul, RangeInclusive, Sub};
|
use std::ops::{Add, Div, Mul, RangeInclusive, Sub};
|
||||||
|
|
||||||
|
@ -130,14 +177,11 @@ pub fn round_to_decimals(value: f64, decimal_places: usize) -> f64 {
|
||||||
.unwrap_or(value)
|
.unwrap_or(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn format_with_minimum_decimals(value: f64, decimals: usize) -> String {
|
pub fn format_with_minimum_decimals(value: f64, decimals: usize) -> String {
|
||||||
format_with_decimals_in_range(value, decimals..=6)
|
format_with_decimals_in_range(value, decimals..=6)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn format_with_decimals_in_range(
|
pub fn format_with_decimals_in_range(value: f64, decimal_range: RangeInclusive<usize>) -> String {
|
||||||
value: f64,
|
|
||||||
decimal_range: RangeInclusive<usize>,
|
|
||||||
) -> String {
|
|
||||||
let min_decimals = *decimal_range.start();
|
let min_decimals = *decimal_range.start();
|
||||||
let max_decimals = *decimal_range.end();
|
let max_decimals = *decimal_range.end();
|
||||||
debug_assert!(min_decimals <= max_decimals);
|
debug_assert!(min_decimals <= max_decimals);
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::{Add, AddAssign, RangeInclusive, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, RangeInclusive, Sub, SubAssign};
|
||||||
|
|
||||||
use crate::math::*;
|
use crate::*;
|
||||||
|
|
||||||
/// A position on screen.
|
/// A position on screen.
|
||||||
///
|
///
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
use crate::math::*;
|
use crate::*;
|
||||||
|
|
||||||
/// A rectangular region of space.
|
/// A rectangular region of space.
|
||||||
///
|
///
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, RangeInclusive, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, RangeInclusive, Sub, SubAssign};
|
||||||
|
|
||||||
use crate::math::*;
|
use crate::*;
|
||||||
|
|
||||||
/// A vector has a direction and length.
|
/// A vector has a direction and length.
|
||||||
/// A [`Vec2`] is often used to represent a size.
|
/// A [`Vec2`] is often used to represent a size.
|
Loading…
Reference in a new issue