Add features extra_asserts and extra_debug_asserts for more asserts
This replaces all debug_asserts with these opt-in asserts Related: https://github.com/emilk/egui/issues/395
This commit is contained in:
parent
bd5a85808a
commit
6e5b52e3bc
24 changed files with 135 additions and 58 deletions
|
@ -7,6 +7,8 @@ NOTE: [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md) and [
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added ⭐
|
||||||
|
* Add features `extra_asserts` and `extra_debug_asserts` to enable additional checks.
|
||||||
|
|
||||||
## 0.12.0 - 2021-05-10 - Multitouch, user memory, window pivots, and improved plots
|
## 0.12.0 - 2021-05-10 - Multitouch, user memory, window pivots, and improved plots
|
||||||
|
|
||||||
|
|
|
@ -31,13 +31,19 @@ default = ["default_fonts", "single_threaded"]
|
||||||
# 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.
|
||||||
default_fonts = ["epaint/default_fonts"]
|
default_fonts = ["epaint/default_fonts"]
|
||||||
|
|
||||||
|
# Enable additional checks if debug assertions are enabled (debug builds).
|
||||||
|
extra_debug_asserts = ["epaint/extra_debug_asserts"]
|
||||||
|
# Always enable additional checks.
|
||||||
|
extra_asserts = ["epaint/extra_asserts"]
|
||||||
|
|
||||||
|
# Add compatability with https://github.com/kvark/mint
|
||||||
|
mint = ["epaint/mint"]
|
||||||
|
|
||||||
persistence = ["serde", "epaint/persistence", "ron"]
|
persistence = ["serde", "epaint/persistence", "ron"]
|
||||||
|
|
||||||
# Only needed if you plan to use the same egui::Context from multiple threads.
|
# Only needed if you plan to use the same egui::Context from multiple threads.
|
||||||
single_threaded = ["epaint/single_threaded"]
|
single_threaded = ["epaint/single_threaded"]
|
||||||
multi_threaded = ["epaint/multi_threaded"]
|
multi_threaded = ["epaint/multi_threaded"]
|
||||||
|
|
||||||
mint = ["epaint/mint"]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|
|
@ -212,7 +212,7 @@ impl<'open> Window<'open> {
|
||||||
if self.scroll.is_none() {
|
if self.scroll.is_none() {
|
||||||
self.scroll = Some(ScrollArea::auto_sized());
|
self.scroll = Some(ScrollArea::auto_sized());
|
||||||
}
|
}
|
||||||
debug_assert!(
|
crate::egui_assert!(
|
||||||
self.scroll.is_some(),
|
self.scroll.is_some(),
|
||||||
"Window::scroll called multiple times"
|
"Window::scroll called multiple times"
|
||||||
);
|
);
|
||||||
|
|
|
@ -70,7 +70,7 @@ impl FrameState {
|
||||||
/// This is the "background" area, what egui doesn't cover with panels (but may cover with windows).
|
/// This is the "background" area, what egui doesn't cover with panels (but may cover with windows).
|
||||||
/// This is also the area to which windows are constrained.
|
/// This is also the area to which windows are constrained.
|
||||||
pub(crate) fn available_rect(&self) -> Rect {
|
pub(crate) fn available_rect(&self) -> Rect {
|
||||||
debug_assert!(
|
crate::egui_assert!(
|
||||||
self.available_rect.is_finite(),
|
self.available_rect.is_finite(),
|
||||||
"Called `available_rect()` before `CtxRef::begin_frame()`"
|
"Called `available_rect()` before `CtxRef::begin_frame()`"
|
||||||
);
|
);
|
||||||
|
@ -79,7 +79,7 @@ impl FrameState {
|
||||||
|
|
||||||
/// Shrink `available_rect`.
|
/// Shrink `available_rect`.
|
||||||
pub(crate) fn allocate_left_panel(&mut self, panel_rect: Rect) {
|
pub(crate) fn allocate_left_panel(&mut self, panel_rect: Rect) {
|
||||||
debug_assert!(
|
crate::egui_assert!(
|
||||||
panel_rect.min.distance(self.available_rect.min) < 0.1,
|
panel_rect.min.distance(self.available_rect.min) < 0.1,
|
||||||
"Mismatching left panel. You must not create a panel from within another panel."
|
"Mismatching left panel. You must not create a panel from within another panel."
|
||||||
);
|
);
|
||||||
|
@ -90,7 +90,7 @@ impl FrameState {
|
||||||
|
|
||||||
/// Shrink `available_rect`.
|
/// Shrink `available_rect`.
|
||||||
pub(crate) fn allocate_top_panel(&mut self, panel_rect: Rect) {
|
pub(crate) fn allocate_top_panel(&mut self, panel_rect: Rect) {
|
||||||
debug_assert!(
|
crate::egui_assert!(
|
||||||
panel_rect.min.distance(self.available_rect.min) < 0.1,
|
panel_rect.min.distance(self.available_rect.min) < 0.1,
|
||||||
"Mismatching top panel. You must not create a panel from within another panel."
|
"Mismatching top panel. You must not create a panel from within another panel."
|
||||||
);
|
);
|
||||||
|
|
|
@ -342,8 +342,8 @@ impl Layout {
|
||||||
/// ## Doing layout
|
/// ## Doing layout
|
||||||
impl Layout {
|
impl Layout {
|
||||||
pub fn align_size_within_rect(&self, size: Vec2, outer: Rect) -> Rect {
|
pub fn align_size_within_rect(&self, size: Vec2, outer: Rect) -> Rect {
|
||||||
debug_assert!(size.x >= 0.0 && size.y >= 0.0);
|
crate::egui_assert!(size.x >= 0.0 && size.y >= 0.0);
|
||||||
debug_assert!(!outer.is_negative());
|
crate::egui_assert!(!outer.is_negative());
|
||||||
self.align2().align_size_within_rect(size, outer)
|
self.align2().align_size_within_rect(size, outer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn region_from_max_rect(&self, max_rect: Rect) -> Region {
|
pub(crate) fn region_from_max_rect(&self, max_rect: Rect) -> Region {
|
||||||
debug_assert!(!max_rect.any_nan());
|
crate::egui_assert!(!max_rect.any_nan());
|
||||||
let mut region = Region {
|
let mut region = Region {
|
||||||
min_rect: Rect::NOTHING, // temporary
|
min_rect: Rect::NOTHING, // temporary
|
||||||
max_rect,
|
max_rect,
|
||||||
|
@ -464,7 +464,7 @@ impl Layout {
|
||||||
/// This is what you then pass to `advance_after_rects`.
|
/// This is what you then pass to `advance_after_rects`.
|
||||||
/// Use `justify_and_align` to get the inner `widget_rect`.
|
/// Use `justify_and_align` to get the inner `widget_rect`.
|
||||||
pub(crate) fn next_frame(&self, region: &Region, child_size: Vec2, spacing: Vec2) -> Rect {
|
pub(crate) fn next_frame(&self, region: &Region, child_size: Vec2, spacing: Vec2) -> Rect {
|
||||||
debug_assert!(child_size.x >= 0.0 && child_size.y >= 0.0);
|
crate::egui_assert!(child_size.x >= 0.0 && child_size.y >= 0.0);
|
||||||
|
|
||||||
if self.main_wrap {
|
if self.main_wrap {
|
||||||
let available_size = self.available_rect_before_wrap(region).size();
|
let available_size = self.available_rect_before_wrap(region).size();
|
||||||
|
@ -543,7 +543,7 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_frame_ignore_wrap(&self, region: &Region, child_size: Vec2) -> Rect {
|
fn next_frame_ignore_wrap(&self, region: &Region, child_size: Vec2) -> Rect {
|
||||||
debug_assert!(child_size.x >= 0.0 && child_size.y >= 0.0);
|
crate::egui_assert!(child_size.x >= 0.0 && child_size.y >= 0.0);
|
||||||
|
|
||||||
let available_rect = self.available_rect_before_wrap_finite(region);
|
let available_rect = self.available_rect_before_wrap_finite(region);
|
||||||
|
|
||||||
|
@ -581,8 +581,8 @@ impl Layout {
|
||||||
|
|
||||||
/// Apply justify (fill width/height) and/or alignment after calling `next_space`.
|
/// Apply justify (fill width/height) and/or alignment after calling `next_space`.
|
||||||
pub(crate) fn justify_and_align(&self, frame: Rect, mut child_size: Vec2) -> Rect {
|
pub(crate) fn justify_and_align(&self, frame: Rect, mut child_size: Vec2) -> Rect {
|
||||||
debug_assert!(child_size.x >= 0.0 && child_size.y >= 0.0);
|
crate::egui_assert!(child_size.x >= 0.0 && child_size.y >= 0.0);
|
||||||
debug_assert!(!frame.is_negative());
|
crate::egui_assert!(!frame.is_negative());
|
||||||
|
|
||||||
if self.horizontal_justify() {
|
if self.horizontal_justify() {
|
||||||
child_size.x = child_size.x.at_least(frame.width()); // fill full width
|
child_size.x = child_size.x.at_least(frame.width()); // fill full width
|
||||||
|
@ -600,7 +600,7 @@ impl Layout {
|
||||||
) -> Rect {
|
) -> Rect {
|
||||||
let frame = self.next_frame_ignore_wrap(region, size);
|
let frame = self.next_frame_ignore_wrap(region, size);
|
||||||
let rect = self.align_size_within_rect(size, frame);
|
let rect = self.align_size_within_rect(size, frame);
|
||||||
debug_assert!((rect.size() - size).length() < 1.0);
|
crate::egui_assert!((rect.size() - size).length() < 1.0);
|
||||||
rect
|
rect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -418,6 +418,22 @@ macro_rules! github_link_file {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// An assert that is only active when `egui` is compiled with the `egui_assert` feature
|
||||||
|
/// or with the `debug_egui_assert` feature in debug builds.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! egui_assert {
|
||||||
|
($($arg:tt)*) => {
|
||||||
|
if cfg!(any(
|
||||||
|
feature = "extra_asserts",
|
||||||
|
all(feature = "extra_debug_asserts", debug_assertions),
|
||||||
|
)) {
|
||||||
|
assert!($($arg)*);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// egui supports around 1216 emojis in total.
|
/// egui supports around 1216 emojis in total.
|
||||||
/// Here are some of the most useful:
|
/// Here are some of the most useful:
|
||||||
/// ∞⊗⎗⎘⎙⏏⏴⏵⏶⏷
|
/// ∞⊗⎗⎘⎙⏏⏴⏵⏶⏷
|
||||||
|
|
|
@ -133,8 +133,8 @@ impl Placer {
|
||||||
|
|
||||||
/// Apply justify or alignment after calling `next_space`.
|
/// Apply justify or alignment after calling `next_space`.
|
||||||
pub(crate) fn justify_and_align(&self, rect: Rect, child_size: Vec2) -> Rect {
|
pub(crate) fn justify_and_align(&self, rect: Rect, child_size: Vec2) -> Rect {
|
||||||
debug_assert!(!rect.any_nan());
|
crate::egui_assert!(!rect.any_nan());
|
||||||
debug_assert!(!child_size.any_nan());
|
crate::egui_assert!(!child_size.any_nan());
|
||||||
|
|
||||||
if let Some(grid) = &self.grid {
|
if let Some(grid) = &self.grid {
|
||||||
grid.justify_and_align(rect, child_size)
|
grid.justify_and_align(rect, child_size)
|
||||||
|
@ -146,7 +146,7 @@ impl Placer {
|
||||||
/// Advance the cursor by this many points.
|
/// Advance the cursor by this many points.
|
||||||
/// [`Self::min_rect`] will expand to contain the cursor.
|
/// [`Self::min_rect`] will expand to contain the cursor.
|
||||||
pub(crate) fn advance_cursor(&mut self, amount: f32) {
|
pub(crate) fn advance_cursor(&mut self, amount: f32) {
|
||||||
debug_assert!(
|
crate::egui_assert!(
|
||||||
self.grid.is_none(),
|
self.grid.is_none(),
|
||||||
"You cannot advance the cursor when in a grid layout"
|
"You cannot advance the cursor when in a grid layout"
|
||||||
);
|
);
|
||||||
|
|
|
@ -442,8 +442,8 @@ impl Response {
|
||||||
/// For instance `a.union(b).hovered` means "was either a or b hovered?".
|
/// For instance `a.union(b).hovered` means "was either a or b hovered?".
|
||||||
pub fn union(&self, other: Self) -> Self {
|
pub fn union(&self, other: Self) -> Self {
|
||||||
assert!(self.ctx == other.ctx);
|
assert!(self.ctx == other.ctx);
|
||||||
debug_assert_eq!(
|
crate::egui_assert!(
|
||||||
self.layer_id, other.layer_id,
|
self.layer_id == other.layer_id,
|
||||||
"It makes no sense to combine Responses from two different layers"
|
"It makes no sense to combine Responses from two different layers"
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -78,7 +78,7 @@ impl Ui {
|
||||||
|
|
||||||
/// Create a new `Ui` at a specific region.
|
/// Create a new `Ui` at a specific region.
|
||||||
pub fn child_ui(&mut self, max_rect: Rect, layout: Layout) -> Self {
|
pub fn child_ui(&mut self, max_rect: Rect, layout: Layout) -> Self {
|
||||||
debug_assert!(!max_rect.any_nan());
|
crate::egui_assert!(!max_rect.any_nan());
|
||||||
let next_auto_id_source = Id::new(self.next_auto_id_source).with("child").value();
|
let next_auto_id_source = Id::new(self.next_auto_id_source).with("child").value();
|
||||||
self.next_auto_id_source = self.next_auto_id_source.wrapping_add(1);
|
self.next_auto_id_source = self.next_auto_id_source.wrapping_add(1);
|
||||||
|
|
||||||
|
@ -723,7 +723,7 @@ impl Ui {
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
add_contents: Box<dyn FnOnce(&mut Self) -> R + 'c>,
|
add_contents: Box<dyn FnOnce(&mut Self) -> R + 'c>,
|
||||||
) -> InnerResponse<R> {
|
) -> InnerResponse<R> {
|
||||||
debug_assert!(desired_size.x >= 0.0 && desired_size.y >= 0.0);
|
crate::egui_assert!(desired_size.x >= 0.0 && desired_size.y >= 0.0);
|
||||||
let item_spacing = self.spacing().item_spacing;
|
let item_spacing = self.spacing().item_spacing;
|
||||||
let frame_rect = self.placer.next_space(desired_size, item_spacing);
|
let frame_rect = self.placer.next_space(desired_size, item_spacing);
|
||||||
let child_rect = self.placer.justify_and_align(frame_rect, desired_size);
|
let child_rect = self.placer.justify_and_align(frame_rect, desired_size);
|
||||||
|
|
|
@ -104,7 +104,7 @@ where
|
||||||
/// Values must be added with a monotonically increasing time, or at least not decreasing.
|
/// Values must be added with a monotonically increasing time, or at least not decreasing.
|
||||||
pub fn add(&mut self, now: f64, value: T) {
|
pub fn add(&mut self, now: f64, value: T) {
|
||||||
if let Some((last_time, _)) = self.values.back() {
|
if let Some((last_time, _)) = self.values.back() {
|
||||||
debug_assert!(now >= *last_time, "Time shouldn't move backwards");
|
crate::egui_assert!(now >= *last_time, "Time shouldn't move backwards");
|
||||||
}
|
}
|
||||||
self.total_count += 1;
|
self.total_count += 1;
|
||||||
self.values.push_back((now, value));
|
self.values.push_back((now, value));
|
||||||
|
|
|
@ -523,7 +523,7 @@ fn value_from_normalized(normalized: f64, range: RangeInclusive<f64>, spec: &Sli
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(
|
crate::egui_assert!(
|
||||||
min.is_finite() && max.is_finite(),
|
min.is_finite() && max.is_finite(),
|
||||||
"You should use a logarithmic range"
|
"You should use a logarithmic range"
|
||||||
);
|
);
|
||||||
|
@ -572,7 +572,7 @@ fn normalized_from_value(value: f64, range: RangeInclusive<f64>, spec: &SliderSp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(
|
crate::egui_assert!(
|
||||||
min.is_finite() && max.is_finite(),
|
min.is_finite() && max.is_finite(),
|
||||||
"You should use a logarithmic range"
|
"You should use a logarithmic range"
|
||||||
);
|
);
|
||||||
|
@ -620,6 +620,6 @@ fn logaritmic_zero_cutoff(min: f64, max: f64) -> f64 {
|
||||||
};
|
};
|
||||||
|
|
||||||
let cutoff = min_magnitude / (min_magnitude + max_magnitude);
|
let cutoff = min_magnitude / (min_magnitude + max_magnitude);
|
||||||
debug_assert!(0.0 <= cutoff && cutoff <= 1.0);
|
crate::egui_assert!(0.0 <= cutoff && cutoff <= 1.0);
|
||||||
cutoff
|
cutoff
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,11 @@ http = ["image", "epi/http"]
|
||||||
persistence = ["egui/persistence", "epi/persistence", "serde"]
|
persistence = ["egui/persistence", "epi/persistence", "serde"]
|
||||||
syntax_highlighting = ["syntect"]
|
syntax_highlighting = ["syntect"]
|
||||||
|
|
||||||
|
# Enable additional checks if debug assertions are enabled (debug builds).
|
||||||
|
extra_debug_asserts = ["egui/extra_debug_asserts"]
|
||||||
|
# Always enable additional checks.
|
||||||
|
extra_asserts = ["egui/extra_asserts"]
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "benchmark"
|
name = "benchmark"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
|
@ -20,8 +20,14 @@ include = [
|
||||||
[lib]
|
[lib]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
# Add compatability with https://github.com/kvark/mint
|
||||||
mint = { version = "0.5.6", optional = true }
|
mint = { version = "0.5.6", optional = true }
|
||||||
serde = { version = "1", features = ["derive"], optional = true }
|
serde = { version = "1", features = ["derive"], optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
|
# Enable additional checks if debug assertions are enabled (debug builds).
|
||||||
|
extra_debug_asserts = []
|
||||||
|
# Always enable additional checks.
|
||||||
|
extra_asserts = []
|
||||||
|
|
|
@ -163,7 +163,7 @@ pub fn remap<T>(x: T, from: RangeInclusive<T>, to: RangeInclusive<T>) -> T
|
||||||
where
|
where
|
||||||
T: Real,
|
T: Real,
|
||||||
{
|
{
|
||||||
debug_assert!(from.start() != from.end());
|
crate::emath_assert!(from.start() != from.end());
|
||||||
let t = (x - *from.start()) / (*from.end() - *from.start());
|
let t = (x - *from.start()) / (*from.end() - *from.start());
|
||||||
lerp(to, t)
|
lerp(to, t)
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ where
|
||||||
} else if *from.end() <= x {
|
} else if *from.end() <= x {
|
||||||
*to.end()
|
*to.end()
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(from.start() != from.end());
|
crate::emath_assert!(from.start() != from.end());
|
||||||
let t = (x - *from.start()) / (*from.end() - *from.start());
|
let t = (x - *from.start()) / (*from.end() - *from.start());
|
||||||
// Ensure no numerical inaccuracies sneak in:
|
// Ensure no numerical inaccuracies sneak in:
|
||||||
if T::one() <= t {
|
if T::one() <= t {
|
||||||
|
@ -200,7 +200,7 @@ pub fn clamp<T>(x: T, range: RangeInclusive<T>) -> T
|
||||||
where
|
where
|
||||||
T: Copy + PartialOrd,
|
T: Copy + PartialOrd,
|
||||||
{
|
{
|
||||||
debug_assert!(range.start() <= range.end());
|
crate::emath_assert!(range.start() <= range.end());
|
||||||
if x <= *range.start() {
|
if x <= *range.start() {
|
||||||
*range.start()
|
*range.start()
|
||||||
} else if *range.end() <= x {
|
} else if *range.end() <= x {
|
||||||
|
@ -225,8 +225,8 @@ pub fn format_with_minimum_decimals(value: f64, decimals: usize) -> String {
|
||||||
pub fn format_with_decimals_in_range(value: f64, decimal_range: RangeInclusive<usize>) -> String {
|
pub fn format_with_decimals_in_range(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);
|
crate::emath_assert!(min_decimals <= max_decimals);
|
||||||
debug_assert!(max_decimals < 100);
|
crate::emath_assert!(max_decimals < 100);
|
||||||
let max_decimals = max_decimals.min(16);
|
let max_decimals = max_decimals.min(16);
|
||||||
let min_decimals = min_decimals.min(max_decimals);
|
let min_decimals = min_decimals.min(max_decimals);
|
||||||
|
|
||||||
|
@ -381,3 +381,19 @@ fn test_normalized_angle() {
|
||||||
almost_eq!(normalized_angle(TAU), 0.0);
|
almost_eq!(normalized_angle(TAU), 0.0);
|
||||||
almost_eq!(normalized_angle(2.7 * TAU), -0.3 * TAU);
|
almost_eq!(normalized_angle(2.7 * TAU), -0.3 * TAU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// An assert that is only active when `egui` is compiled with the `egui_assert` feature
|
||||||
|
/// or with the `debug_egui_assert` feature in debug builds.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! emath_assert {
|
||||||
|
($($arg:tt)*) => {
|
||||||
|
if cfg!(any(
|
||||||
|
feature = "extra_asserts",
|
||||||
|
all(feature = "extra_debug_asserts", debug_assertions),
|
||||||
|
)) {
|
||||||
|
assert!($($arg)*);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ impl Rot2 {
|
||||||
c: self.c / l,
|
c: self.c / l,
|
||||||
s: self.s / l,
|
s: self.s / l,
|
||||||
};
|
};
|
||||||
debug_assert!(ret.is_finite());
|
crate::emath_assert!(ret.is_finite());
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub fn best_in_range_f64(min: f64, max: f64) -> f64 {
|
||||||
if !max.is_finite() {
|
if !max.is_finite() {
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
debug_assert!(min.is_finite() && max.is_finite());
|
crate::emath_assert!(min.is_finite() && max.is_finite());
|
||||||
|
|
||||||
let min_exponent = min.log10();
|
let min_exponent = min.log10();
|
||||||
let max_exponent = max.log10();
|
let max_exponent = max.log10();
|
||||||
|
@ -82,7 +82,7 @@ fn is_integer(f: f64) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_decimal_string(v: f64) -> [i32; NUM_DECIMALS] {
|
fn to_decimal_string(v: f64) -> [i32; NUM_DECIMALS] {
|
||||||
debug_assert!(v < 10.0, "{:?}", v);
|
crate::emath_assert!(v < 10.0, "{:?}", v);
|
||||||
let mut digits = [0; NUM_DECIMALS];
|
let mut digits = [0; NUM_DECIMALS];
|
||||||
let mut v = v.abs();
|
let mut v = v.abs();
|
||||||
for r in digits.iter_mut() {
|
for r in digits.iter_mut() {
|
||||||
|
@ -104,7 +104,7 @@ fn from_decimal_string(s: &[i32]) -> f64 {
|
||||||
|
|
||||||
/// Find the simplest integer in the range [min, max]
|
/// Find the simplest integer in the range [min, max]
|
||||||
fn simplest_digit_closed_range(min: i32, max: i32) -> i32 {
|
fn simplest_digit_closed_range(min: i32, max: i32) -> i32 {
|
||||||
debug_assert!(1 <= min && min <= max && max <= 9);
|
crate::emath_assert!(1 <= min && min <= max && max <= 9);
|
||||||
if min <= 5 && 5 <= max {
|
if min <= 5 && 5 <= max {
|
||||||
5
|
5
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -33,15 +33,22 @@ serde = { version = "1", features = ["derive"], optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["multi_threaded", "default_fonts"]
|
default = ["multi_threaded", "default_fonts"]
|
||||||
persistence = ["serde", "emath/serde"]
|
|
||||||
|
|
||||||
# If set, epaint will use `include_bytes!` to bundle some fonts.
|
# If set, epaint 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.
|
||||||
default_fonts = []
|
default_fonts = []
|
||||||
|
|
||||||
|
# Enable additional checks if debug assertions are enabled (debug builds).
|
||||||
|
extra_debug_asserts = ["emath/extra_debug_asserts"]
|
||||||
|
# Always enable additional checks.
|
||||||
|
extra_asserts = ["emath/extra_asserts"]
|
||||||
|
|
||||||
|
# Add compatability with https://github.com/kvark/mint
|
||||||
|
mint = ["emath/mint"]
|
||||||
|
|
||||||
|
persistence = ["serde", "emath/serde"]
|
||||||
|
|
||||||
single_threaded = ["atomic_refcell"]
|
single_threaded = ["atomic_refcell"]
|
||||||
|
|
||||||
# Only needed if you plan to use the same fonts from multiple threads.
|
# Only needed if you plan to use the same fonts from multiple threads.
|
||||||
multi_threaded = ["parking_lot"]
|
multi_threaded = ["parking_lot"]
|
||||||
|
|
||||||
mint = ["emath/mint"]
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ impl Color32 {
|
||||||
|
|
||||||
/// Multiply with 0.5 to make color half as opaque.
|
/// Multiply with 0.5 to make color half as opaque.
|
||||||
pub fn linear_multiply(self, factor: f32) -> Color32 {
|
pub fn linear_multiply(self, factor: f32) -> Color32 {
|
||||||
debug_assert!(0.0 <= factor && factor <= 1.0);
|
crate::epaint_assert!(0.0 <= factor && factor <= 1.0);
|
||||||
// As an unfortunate side-effect of using premultiplied alpha
|
// As an unfortunate side-effect of using premultiplied alpha
|
||||||
// we need a somewhat expensive conversion to linear space and back.
|
// we need a somewhat expensive conversion to linear space and back.
|
||||||
Rgba::from(self).multiply(factor).into()
|
Rgba::from(self).multiply(factor).into()
|
||||||
|
@ -214,22 +214,22 @@ impl Rgba {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_luminance_alpha(l: f32, a: f32) -> Self {
|
pub fn from_luminance_alpha(l: f32, a: f32) -> Self {
|
||||||
debug_assert!(0.0 <= l && l <= 1.0);
|
crate::epaint_assert!(0.0 <= l && l <= 1.0);
|
||||||
debug_assert!(0.0 <= a && a <= 1.0);
|
crate::epaint_assert!(0.0 <= a && a <= 1.0);
|
||||||
Self([l * a, l * a, l * a, a])
|
Self([l * a, l * a, l * a, a])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transparent black
|
/// Transparent black
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_black_alpha(a: f32) -> Self {
|
pub fn from_black_alpha(a: f32) -> Self {
|
||||||
debug_assert!(0.0 <= a && a <= 1.0);
|
crate::epaint_assert!(0.0 <= a && a <= 1.0);
|
||||||
Self([0.0, 0.0, 0.0, a])
|
Self([0.0, 0.0, 0.0, a])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transparent white
|
/// Transparent white
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_white_alpha(a: f32) -> Self {
|
pub fn from_white_alpha(a: f32) -> Self {
|
||||||
debug_assert!(0.0 <= a && a <= 1.0);
|
crate::epaint_assert!(0.0 <= a && a <= 1.0);
|
||||||
Self([a, a, a, a])
|
Self([a, a, a, a])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,3 +159,19 @@ pub struct ClippedMesh(
|
||||||
/// The shape
|
/// The shape
|
||||||
pub Mesh,
|
pub Mesh,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// An assert that is only active when `egui` is compiled with the `egui_assert` feature
|
||||||
|
/// or with the `debug_egui_assert` feature in debug builds.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! epaint_assert {
|
||||||
|
($($arg:tt)*) => {
|
||||||
|
if cfg!(any(
|
||||||
|
feature = "extra_asserts",
|
||||||
|
all(feature = "extra_debug_asserts", debug_assertions),
|
||||||
|
)) {
|
||||||
|
assert!($($arg)*);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ impl Mesh {
|
||||||
|
|
||||||
/// Append all the indices and vertices of `other` to `self`.
|
/// Append all the indices and vertices of `other` to `self`.
|
||||||
pub fn append(&mut self, other: Mesh) {
|
pub fn append(&mut self, other: Mesh) {
|
||||||
debug_assert!(other.is_valid());
|
crate::epaint_assert!(other.is_valid());
|
||||||
|
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
*self = other;
|
*self = other;
|
||||||
|
@ -94,7 +94,7 @@ impl Mesh {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn colored_vertex(&mut self, pos: Pos2, color: Color32) {
|
pub fn colored_vertex(&mut self, pos: Pos2, color: Color32) {
|
||||||
debug_assert!(self.texture_id == TextureId::Egui);
|
crate::epaint_assert!(self.texture_id == TextureId::Egui);
|
||||||
self.vertices.push(Vertex {
|
self.vertices.push(Vertex {
|
||||||
pos,
|
pos,
|
||||||
uv: WHITE_UV,
|
uv: WHITE_UV,
|
||||||
|
@ -157,7 +157,7 @@ impl Mesh {
|
||||||
/// Uniformly colored rectangle.
|
/// Uniformly colored rectangle.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn add_colored_rect(&mut self, rect: Rect, color: Color32) {
|
pub fn add_colored_rect(&mut self, rect: Rect, color: Color32) {
|
||||||
debug_assert!(self.texture_id == TextureId::Egui);
|
crate::epaint_assert!(self.texture_id == TextureId::Egui);
|
||||||
self.add_rect_with_uv(rect, [WHITE_UV, WHITE_UV].into(), color)
|
self.add_rect_with_uv(rect, [WHITE_UV, WHITE_UV].into(), color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ impl Mesh {
|
||||||
/// Splits this mesh into many smaller meshes (if needed)
|
/// Splits this mesh into many smaller meshes (if needed)
|
||||||
/// where the smaller meshes have 16-bit indices.
|
/// where the smaller meshes have 16-bit indices.
|
||||||
pub fn split_to_u16(self) -> Vec<Mesh16> {
|
pub fn split_to_u16(self) -> Vec<Mesh16> {
|
||||||
debug_assert!(self.is_valid());
|
crate::epaint_assert!(self.is_valid());
|
||||||
|
|
||||||
const MAX_SIZE: u32 = 1 << 16;
|
const MAX_SIZE: u32 = 1 << 16;
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ impl Mesh {
|
||||||
vertices: self.vertices[(min_vindex as usize)..=(max_vindex as usize)].to_vec(),
|
vertices: self.vertices[(min_vindex as usize)..=(max_vindex as usize)].to_vec(),
|
||||||
texture_id: self.texture_id,
|
texture_id: self.texture_id,
|
||||||
};
|
};
|
||||||
debug_assert!(mesh.is_valid());
|
crate::epaint_assert!(mesh.is_valid());
|
||||||
output.push(mesh);
|
output.push(mesh);
|
||||||
}
|
}
|
||||||
output
|
output
|
||||||
|
|
|
@ -147,7 +147,7 @@ impl Shape {
|
||||||
/// ## Operations
|
/// ## Operations
|
||||||
impl Shape {
|
impl Shape {
|
||||||
pub fn mesh(mesh: Mesh) -> Self {
|
pub fn mesh(mesh: Mesh) -> Self {
|
||||||
debug_assert!(mesh.is_valid());
|
crate::epaint_assert!(mesh.is_valid());
|
||||||
Self::Mesh(mesh)
|
Self::Mesh(mesh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -456,7 +456,7 @@ fn stroke_path(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mul_color(color: Color32, factor: f32) -> Color32 {
|
fn mul_color(color: Color32, factor: f32) -> Color32 {
|
||||||
debug_assert!(0.0 <= factor && factor <= 1.0);
|
crate::epaint_assert!(0.0 <= factor && factor <= 1.0);
|
||||||
// As an unfortunate side-effect of using premultiplied alpha
|
// As an unfortunate side-effect of using premultiplied alpha
|
||||||
// we need a somewhat expensive conversion to linear space and back.
|
// we need a somewhat expensive conversion to linear space and back.
|
||||||
color.linear_multiply(factor)
|
color.linear_multiply(factor)
|
||||||
|
@ -528,7 +528,7 @@ impl Tessellator {
|
||||||
if mesh.is_valid() {
|
if mesh.is_valid() {
|
||||||
out.append(mesh);
|
out.append(mesh);
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(false, "Invalid Mesh in Shape::Mesh");
|
crate::epaint_assert!(false, "Invalid Mesh in Shape::Mesh");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Shape::LineSegment { points, stroke } => {
|
Shape::LineSegment { points, stroke } => {
|
||||||
|
@ -553,7 +553,7 @@ impl Tessellator {
|
||||||
}
|
}
|
||||||
|
|
||||||
if fill != Color32::TRANSPARENT {
|
if fill != Color32::TRANSPARENT {
|
||||||
debug_assert!(
|
crate::epaint_assert!(
|
||||||
closed,
|
closed,
|
||||||
"You asked to fill a path that is not closed. That makes no sense."
|
"You asked to fill a path that is not closed. That makes no sense."
|
||||||
);
|
);
|
||||||
|
@ -641,7 +641,10 @@ impl Tessellator {
|
||||||
if color == Color32::TRANSPARENT || galley.is_empty() {
|
if color == Color32::TRANSPARENT || galley.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(any(
|
||||||
|
feature = "extra_asserts",
|
||||||
|
all(feature = "extra_debug_asserts", debug_assertions),
|
||||||
|
)) {
|
||||||
galley.sanity_check();
|
galley.sanity_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,7 +793,7 @@ pub fn tessellate_shapes(
|
||||||
}
|
}
|
||||||
|
|
||||||
for ClippedMesh(_, mesh) in &clipped_meshes {
|
for ClippedMesh(_, mesh) in &clipped_meshes {
|
||||||
debug_assert!(mesh.is_valid(), "Tessellator generated invalid Mesh");
|
crate::epaint_assert!(mesh.is_valid(), "Tessellator generated invalid Mesh");
|
||||||
}
|
}
|
||||||
|
|
||||||
clipped_meshes
|
clipped_meshes
|
||||||
|
|
|
@ -467,7 +467,7 @@ impl Font {
|
||||||
let mut out_rows = vec![];
|
let mut out_rows = vec![];
|
||||||
|
|
||||||
for (i, (x, chr)) in full_x_offsets.iter().skip(1).zip(text.chars()).enumerate() {
|
for (i, (x, chr)) in full_x_offsets.iter().skip(1).zip(text.chars()).enumerate() {
|
||||||
debug_assert!(chr != '\n');
|
crate::epaint_assert!(chr != '\n');
|
||||||
let potential_row_width = first_row_indentation + x - row_start_x;
|
let potential_row_width = first_row_indentation + x - row_start_x;
|
||||||
|
|
||||||
if potential_row_width > max_width_in_points {
|
if potential_row_width > max_width_in_points {
|
||||||
|
|
|
@ -158,9 +158,9 @@ impl Galley {
|
||||||
row.sanity_check();
|
row.sanity_check();
|
||||||
char_count += row.char_count_including_newline();
|
char_count += row.char_count_including_newline();
|
||||||
}
|
}
|
||||||
debug_assert_eq!(char_count, self.text.chars().count());
|
crate::epaint_assert!(char_count == self.text.chars().count());
|
||||||
if let Some(last_row) = self.rows.last() {
|
if let Some(last_row) = self.rows.last() {
|
||||||
debug_assert!(
|
crate::epaint_assert!(
|
||||||
!last_row.ends_with_newline,
|
!last_row.ends_with_newline,
|
||||||
"If the text ends with '\\n', there would be an empty row last.\n\
|
"If the text ends with '\\n', there would be an empty row last.\n\
|
||||||
Galley: {:#?}",
|
Galley: {:#?}",
|
||||||
|
@ -304,7 +304,7 @@ impl Galley {
|
||||||
|
|
||||||
pub fn end_rcursor(&self) -> RCursor {
|
pub fn end_rcursor(&self) -> RCursor {
|
||||||
if let Some(last_row) = self.rows.last() {
|
if let Some(last_row) = self.rows.last() {
|
||||||
debug_assert!(!last_row.ends_with_newline);
|
crate::epaint_assert!(!last_row.ends_with_newline);
|
||||||
RCursor {
|
RCursor {
|
||||||
row: self.rows.len() - 1,
|
row: self.rows.len() - 1,
|
||||||
column: last_row.char_count_excluding_newline(),
|
column: last_row.char_count_excluding_newline(),
|
||||||
|
@ -361,7 +361,7 @@ impl Galley {
|
||||||
pcursor_it.offset += row.char_count_including_newline();
|
pcursor_it.offset += row.char_count_including_newline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug_assert_eq!(ccursor_it, self.end().ccursor);
|
crate::epaint_assert!(ccursor_it == self.end().ccursor);
|
||||||
Cursor {
|
Cursor {
|
||||||
ccursor: ccursor_it, // clamp
|
ccursor: ccursor_it, // clamp
|
||||||
rcursor: self.end_rcursor(),
|
rcursor: self.end_rcursor(),
|
||||||
|
|
Loading…
Reference in a new issue