1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-02 06:40:06 -04:00

Merge branch 'lucas/atoms-preferred-size' into lucas/experiments/measure-widget-size

# Conflicts:
#	crates/egui/src/ui.rs
#	crates/egui/src/widgets/button.rs
#	crates/egui/src/widgets/label.rs
#	crates/egui_demo_lib/src/demo/popups.rs
#	crates/egui_extras/src/layout.rs
#	crates/epaint/src/text/text_layout_types.rs
This commit is contained in:
lucasmerlin
2025-06-16 09:52:22 +02:00
389 changed files with 8660 additions and 3857 deletions

View File

@@ -5,10 +5,10 @@ authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
description = "Example library for egui"
edition.workspace = true
rust-version.workspace = true
homepage = "https://github.com/emilk/egui/tree/master/crates/egui_demo_lib"
homepage = "https://github.com/emilk/egui/tree/main/crates/egui_demo_lib"
license.workspace = true
readme = "README.md"
repository = "https://github.com/emilk/egui/tree/master/crates/egui_demo_lib"
repository = "https://github.com/emilk/egui/tree/main/crates/egui_demo_lib"
categories = ["gui", "graphics"]
keywords = ["glow", "egui", "gui", "gamedev"]
include = [
@@ -16,7 +16,7 @@ include = [
"../LICENSE-MIT",
"**/*.rs",
"Cargo.toml",
"data/icon.png",
"data/*",
]
[lints]
@@ -43,7 +43,7 @@ syntect = ["egui_extras/syntect"]
[dependencies]
egui = { workspace = true, default-features = false, features = ["color-hex"] }
egui_extras = { workspace = true, features = ["default"] }
egui_extras = { workspace = true, features = ["image", "svg"] }
unicode_names2 = { version = "0.6.0", default-features = false } # this old version has fewer dependencies
@@ -56,8 +56,12 @@ serde = { workspace = true, optional = true }
[dev-dependencies]
criterion.workspace = true
egui_kittest = { workspace = true, features = ["wgpu", "snapshot"] }
egui = { workspace = true, features = ["default_fonts"] }
egui_extras = { workspace = true, features = ["image", "svg"] }
egui_kittest = { workspace = true, features = ["wgpu", "snapshot"] }
image = { workspace = true, features = ["png"] }
mimalloc.workspace = true # for benchmarks
rand = "0.9"
[[bench]]
name = "benchmark"

View File

@@ -14,3 +14,19 @@ The demo library is a separate crate for three reasons:
* To remove the amount of code in `egui` proper.
* To make it easy for 3rd party egui integrations to use it for tests.
- See for instance https://github.com/not-fl3/egui-miniquad/blob/master/examples/demo.rs
This crate also contains benchmarks for egui.
Run them with
```bash
# Run all benchmarks
cargo bench -p egui_demo_lib
# Run a single benchmark
cargo bench -p egui_demo_lib "benchmark name"
# Profile benchmarks with cargo-flamegraph (--root flag is necessary for MacOS)
CARGO_PROFILE_BENCH_DEBUG=true cargo flamegraph --bench benchmark --root -p egui_demo_lib -- --bench "benchmark name"
# Profile with cargo-instruments
CARGO_PROFILE_BENCH_DEBUG=true cargo instruments --profile bench --bench benchmark -p egui_demo_lib -t time -- --bench "benchmark name"
```

View File

@@ -1,7 +1,22 @@
use criterion::{criterion_group, criterion_main, Criterion};
use std::fmt::Write as _;
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use egui::epaint::TextShape;
use egui::load::SizedTexture;
use egui::{Button, Id, RichText, TextureId, Ui, UiBuilder, Vec2};
use egui_demo_lib::LOREM_IPSUM_LONG;
use rand::Rng as _;
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; // Much faster allocator
/// Each iteration should be called in their own `Ui` with an intentional id clash,
/// to prevent the Context from building a massive map of `WidgetRects` (which would slow the test,
/// causing unreliable results).
fn create_benchmark_ui(ctx: &egui::Context) -> Ui {
Ui::new(ctx.clone(), Id::new("clashing_id"), UiBuilder::new())
}
pub fn criterion_benchmark(c: &mut Criterion) {
use egui::RawInput;
@@ -52,17 +67,71 @@ pub fn criterion_benchmark(c: &mut Criterion) {
{
let ctx = egui::Context::default();
let _ = ctx.run(RawInput::default(), |ctx| {
egui::CentralPanel::default().show(ctx, |ui| {
c.bench_function("label &str", |b| {
b.iter(|| {
c.bench_function("label &str", |b| {
b.iter_batched_ref(
|| create_benchmark_ui(ctx),
|ui| {
ui.label("the quick brown fox jumps over the lazy dog");
});
});
c.bench_function("label format!", |b| {
b.iter(|| {
},
BatchSize::LargeInput,
);
});
c.bench_function("label format!", |b| {
b.iter_batched_ref(
|| create_benchmark_ui(ctx),
|ui| {
ui.label("the quick brown fox jumps over the lazy dog".to_owned());
});
});
},
BatchSize::LargeInput,
);
});
});
}
{
let ctx = egui::Context::default();
let _ = ctx.run(RawInput::default(), |ctx| {
let mut group = c.benchmark_group("button");
// To ensure we have a valid image, let's use the font texture. The size
// shouldn't be important for this benchmark.
let image = SizedTexture::new(TextureId::default(), Vec2::splat(16.0));
group.bench_function("1_button_text", |b| {
b.iter_batched_ref(
|| create_benchmark_ui(ctx),
|ui| {
ui.add(Button::new("Hello World"));
},
BatchSize::LargeInput,
);
});
group.bench_function("2_button_text_image", |b| {
b.iter_batched_ref(
|| create_benchmark_ui(ctx),
|ui| {
ui.add(Button::image_and_text(image, "Hello World"));
},
BatchSize::LargeInput,
);
});
group.bench_function("3_button_text_image_right_text", |b| {
b.iter_batched_ref(
|| create_benchmark_ui(ctx),
|ui| {
ui.add(Button::image_and_text(image, "Hello World").right_text(""));
},
BatchSize::LargeInput,
);
});
group.bench_function("4_button_italic", |b| {
b.iter_batched_ref(
|| create_benchmark_ui(ctx),
|ui| {
ui.add(Button::new(RichText::new("Hello World").italics()));
},
BatchSize::LargeInput,
);
});
});
}
@@ -128,6 +197,30 @@ pub fn criterion_benchmark(c: &mut Criterion) {
});
});
c.bench_function("text_layout_cached_many_lines_modified", |b| {
const NUM_LINES: usize = 2_000;
let mut string = String::new();
for _ in 0..NUM_LINES {
for i in 0..30_u8 {
write!(string, "{i:02X} ").unwrap();
}
string.push('\n');
}
let mut rng = rand::rng();
b.iter(|| {
fonts.begin_pass(pixels_per_point, max_texture_side);
// Delete a random character, simulating a user making an edit in a long file:
let mut new_string = string.clone();
let idx = rng.random_range(0..string.len());
new_string.remove(idx);
fonts.layout(new_string, font_id.clone(), text_color, wrap_width);
});
});
let galley = fonts.layout(LOREM_IPSUM_LONG.to_owned(), font_id, text_color, wrap_width);
let font_image_size = fonts.font_image_size();
let prepared_discs = fonts.texture_atlas().lock().prepared_discs();

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
viewBox="0 0 44 44" width="32" height="32">
<g fill="none" stroke="white" stroke-width="3">
<circle cx="22" cy="22" r="19"/>
<path d="M 22,2 V 41"/>
<path d="M 22,2 V 22" transform="rotate(135, 22, 22)"/>
<path d="M 22,2 V 22" transform="rotate(225, 22, 22)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 437 B

View File

@@ -76,12 +76,12 @@ impl crate::View for CodeEditor {
});
});
let mut layouter = |ui: &egui::Ui, string: &str, wrap_width: f32| {
let mut layouter = |ui: &egui::Ui, buf: &dyn egui::TextBuffer, wrap_width: f32| {
let mut layout_job = egui_extras::syntax_highlighting::highlight(
ui.ctx(),
ui.style(),
&theme,
string,
buf.as_str(),
language,
);
layout_job.wrap.max_width = wrap_width;

View File

@@ -105,7 +105,7 @@ impl crate::Demo for CodeExample {
}
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
use crate::View;
use crate::View as _;
egui::Window::new(self.name())
.open(open)
.min_width(375.0)

View File

@@ -3,7 +3,7 @@ use std::collections::BTreeSet;
use super::About;
use crate::is_mobile;
use crate::Demo;
use crate::View;
use crate::View as _;
use egui::containers::menu;
use egui::style::StyleModifier;
use egui::{Context, Modifiers, ScrollArea, Ui};
@@ -13,6 +13,16 @@ struct DemoGroup {
demos: Vec<Box<dyn Demo>>,
}
impl std::ops::Add for DemoGroup {
type Output = Self;
fn add(self, other: Self) -> Self {
let mut demos = self.demos;
demos.extend(other.demos);
Self { demos }
}
}
impl DemoGroup {
pub fn new(demos: Vec<Box<dyn Demo>>) -> Self {
Self { demos }
@@ -100,6 +110,7 @@ impl Default for DemoGroups {
Box::<super::tests::InputTest>::default(),
Box::<super::tests::LayoutTest>::default(),
Box::<super::tests::ManualLayoutTest>::default(),
Box::<super::tests::SvgTest>::default(),
Box::<super::tests::TessellationTest>::default(),
Box::<super::tests::WindowResizeTest>::default(),
]),
@@ -359,14 +370,19 @@ fn file_menu_button(ui: &mut Ui) {
#[cfg(test)]
mod tests {
use crate::{demo::demo_app_windows::DemoGroups, Demo};
use crate::{demo::demo_app_windows::DemoGroups, Demo as _};
use egui::Vec2;
use egui_kittest::kittest::Queryable;
use egui_kittest::kittest::Queryable as _;
use egui_kittest::{Harness, SnapshotOptions, SnapshotResults};
#[test]
fn demos_should_match_snapshot() {
let demos = DemoGroups::default().demos;
let DemoGroups {
demos,
tests,
about: _,
} = DemoGroups::default();
let demos = demos + tests;
let mut results = SnapshotResults::new();
@@ -376,13 +392,10 @@ mod tests {
continue;
}
// Remove the emoji from the demo name
let name = demo
.name()
.split_once(' ')
.map_or(demo.name(), |(_, name)| name);
let name = remove_leading_emoji(demo.name());
let mut harness = Harness::new(|ctx| {
egui_extras::install_image_loaders(ctx);
demo.show(ctx, &mut true);
});
@@ -405,4 +418,13 @@ mod tests {
results.add(harness.try_snapshot_options(&format!("demos/{name}"), &options));
}
}
fn remove_leading_emoji(full_name: &str) -> &str {
if let Some((start, name)) = full_name.split_once(' ') {
if start.len() <= 4 && start.bytes().next().is_some_and(|byte| byte >= 128) {
return name;
}
}
full_name
}
}

View File

@@ -169,7 +169,7 @@ fn char_name(chr: char) -> String {
}
fn special_char_name(chr: char) -> Option<&'static str> {
#[allow(clippy::match_same_arms)] // many "flag"
#[expect(clippy::match_same_arms)] // many "flag"
match chr {
// Special private-use-area extensions found in `emoji-icon-font.ttf`:
// Private use area extensions:

View File

@@ -1,4 +1,4 @@
use egui::{Frame, Label, RichText, Sense, UiBuilder, Widget};
use egui::{Frame, Label, RichText, Sense, UiBuilder, Widget as _};
/// Showcase [`egui::Ui::response`].
#[derive(PartialEq, Eq, Default)]

View File

@@ -1,8 +1,8 @@
use super::{Demo, View};
use egui::{
vec2, Align, Checkbox, CollapsingHeader, Color32, Context, FontId, Resize, RichText, Sense,
Slider, Stroke, TextFormat, TextStyle, Ui, Vec2, Window,
vec2, Align, Align2, Checkbox, CollapsingHeader, Color32, ComboBox, Context, FontId, Resize,
RichText, Sense, Slider, Stroke, TextFormat, TextStyle, Ui, Vec2, Window,
};
/// Showcase some ui code
@@ -16,6 +16,7 @@ pub struct MiscDemoWindow {
custom_collapsing_header: CustomCollapsingHeader,
tree: Tree,
box_painting: BoxPainting,
text_rotation: TextRotation,
dummy_bool: bool,
dummy_usize: usize,
@@ -32,6 +33,7 @@ impl Default for MiscDemoWindow {
custom_collapsing_header: Default::default(),
tree: Tree::demo(),
box_painting: Default::default(),
text_rotation: Default::default(),
dummy_bool: false,
dummy_usize: 0,
@@ -79,6 +81,10 @@ impl View for MiscDemoWindow {
});
});
CollapsingHeader::new("Text rotation")
.default_open(false)
.show(ui, |ui| self.text_rotation.ui(ui));
CollapsingHeader::new("Colors")
.default_open(false)
.show(ui, |ui| {
@@ -730,3 +736,95 @@ fn text_layout_demo(ui: &mut Ui) {
ui.label(job);
}
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
struct TextRotation {
size: Vec2,
angle: f32,
align: egui::Align2,
}
impl Default for TextRotation {
fn default() -> Self {
Self {
size: vec2(200.0, 200.0),
angle: 0.0,
align: egui::Align2::LEFT_TOP,
}
}
}
impl TextRotation {
pub fn ui(&mut self, ui: &mut Ui) {
ui.add(Slider::new(&mut self.angle, 0.0..=2.0 * std::f32::consts::PI).text("angle"));
let default_color = if ui.visuals().dark_mode {
Color32::LIGHT_GRAY
} else {
Color32::DARK_GRAY
};
let aligns = [
(Align2::LEFT_TOP, "LEFT_TOP"),
(Align2::LEFT_CENTER, "LEFT_CENTER"),
(Align2::LEFT_BOTTOM, "LEFT_BOTTOM"),
(Align2::CENTER_TOP, "CENTER_TOP"),
(Align2::CENTER_CENTER, "CENTER_CENTER"),
(Align2::CENTER_BOTTOM, "CENTER_BOTTOM"),
(Align2::RIGHT_TOP, "RIGHT_TOP"),
(Align2::RIGHT_CENTER, "RIGHT_CENTER"),
(Align2::RIGHT_BOTTOM, "RIGHT_BOTTOM"),
];
ComboBox::new("anchor", "Anchor")
.selected_text(aligns.iter().find(|(a, _)| *a == self.align).unwrap().1)
.show_ui(ui, |ui| {
for (align2, name) in &aligns {
ui.selectable_value(&mut self.align, *align2, *name);
}
});
ui.horizontal_wrapped(|ui| {
let (response, painter) = ui.allocate_painter(self.size, Sense::empty());
let rect = response.rect;
let start_pos = self.size / 2.0;
let s = ui.ctx().fonts(|f| {
let mut t = egui::Shape::text(
f,
rect.min + start_pos,
egui::Align2::LEFT_TOP,
"sample_text",
egui::FontId::new(12.0, egui::FontFamily::Proportional),
default_color,
);
if let egui::epaint::Shape::Text(ts) = &mut t {
let new = ts.clone().with_angle_and_anchor(self.angle, self.align);
*ts = new;
};
t
});
if let egui::epaint::Shape::Text(ts) = &s {
let align_pt =
rect.min + start_pos + self.align.pos_in_rect(&ts.galley.rect).to_vec2();
painter.circle(align_pt, 2.0, Color32::RED, (0.0, Color32::RED));
};
painter.rect(
rect,
0.0,
default_color.gamma_multiply(0.3),
(0.0, Color32::BLACK),
egui::StrokeKind::Middle,
);
painter.add(s);
});
}
}

View File

@@ -1,4 +1,4 @@
use egui::{ComboBox, Context, Id, Modal, ProgressBar, Ui, Widget, Window};
use egui::{ComboBox, Context, Id, Modal, ProgressBar, Ui, Widget as _, Window};
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
@@ -163,10 +163,10 @@ impl crate::View for Modals {
#[cfg(test)]
mod tests {
use crate::demo::modals::Modals;
use crate::Demo;
use crate::Demo as _;
use egui::accesskit::Role;
use egui::Key;
use egui_kittest::kittest::Queryable;
use egui_kittest::kittest::Queryable as _;
use egui_kittest::{Harness, SnapshotResults};
#[test]

View File

@@ -2,7 +2,7 @@ use egui::{
emath,
epaint::{self, CubicBezierShape, PathShape, QuadraticBezierShape},
pos2, Color32, Context, Frame, Grid, Pos2, Rect, Sense, Shape, Stroke, StrokeKind, Ui, Vec2,
Widget, Window,
Widget as _, Window,
};
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]

View File

@@ -8,7 +8,6 @@
/// ``` ignore
/// password_ui(ui, &mut my_password);
/// ```
#[allow(clippy::ptr_arg)] // false positive
pub fn password_ui(ui: &mut egui::Ui, password: &mut String) -> egui::Response {
// This widget has its own state — show or hide password characters (`show_plaintext`).
// In this case we use a simple `bool`, but you can also declare your own type.
@@ -62,5 +61,5 @@ pub fn password(password: &mut String) -> impl egui::Widget + '_ {
}
pub fn url_to_file_source_code() -> String {
format!("https://github.com/emilk/egui/blob/master/{}", file!())
format!("https://github.com/emilk/egui/blob/main/{}", file!())
}

View File

@@ -1,8 +1,9 @@
use crate::rust_view_ui;
use egui::color_picker::{color_picker_color32, Alpha};
use egui::containers::menu::{MenuConfig, SubMenuButton};
use egui::{
include_image, Align, Align2, ComboBox, Frame, Id, Layout, Popup, PopupCloseBehavior,
RectAlign, Tooltip, Ui, UiBuilder,
RectAlign, RichText, Tooltip, Ui, UiBuilder,
};
/// Showcase [`Popup`].
@@ -16,6 +17,7 @@ pub struct PopupsDemo {
close_behavior: PopupCloseBehavior,
popup_open: bool,
checked: bool,
color: egui::Color32,
}
impl PopupsDemo {
@@ -25,51 +27,20 @@ impl PopupsDemo {
.gap(self.gap)
.close_behavior(self.close_behavior)
}
}
impl Default for PopupsDemo {
fn default() -> Self {
Self {
align4: RectAlign::default(),
gap: 4.0,
close_behavior: PopupCloseBehavior::CloseOnClick,
popup_open: false,
checked: false,
fn nested_menus(&mut self, ui: &mut Ui) {
ui.set_max_width(200.0); // To make sure we wrap long text
if ui.button("Open…").clicked() {
ui.close();
}
}
}
impl crate::Demo for PopupsDemo {
fn name(&self) -> &'static str {
"\u{2755} Popups"
}
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
egui::Window::new(self.name())
.open(open)
.resizable(false)
.default_width(250.0)
.constrain(false)
.show(ctx, |ui| {
use crate::View as _;
self.ui(ui);
});
}
}
fn nested_menus(ui: &mut egui::Ui, checked: &mut bool) {
ui.set_max_width(200.0); // To make sure we wrap long text
if ui.button("Open…").clicked() {
ui.close();
}
ui.menu_button("Popups can have submenus", |ui| {
ui.menu_button("SubMenu", |ui| {
if ui.button("Open…").clicked() {
ui.close();
}
let _ = ui.button("Item");
ui.menu_button("Recursive", |ui| nested_menus(ui, checked));
ui.menu_button("Popups can have submenus", |ui| {
ui.menu_button("SubMenu", |ui| {
if ui.button("Open…").clicked() {
ui.close();
}
let _ = ui.button("Item");
ui.menu_button("Recursive", |ui| self.nested_menus(ui));
// if ui.button(if *checked { "short" } else { "Very long text for this item that should be wrapped" }).clicked() {
// *checked = !*checked;
@@ -111,11 +82,62 @@ fn nested_menus(ui: &mut egui::Ui, checked: &mut bool) {
SubMenuButton::new("Always CloseOnClickOutside")
.config(MenuConfig::new().close_behavior(PopupCloseBehavior::CloseOnClickOutside))
.ui(ui, |ui| {
ui.checkbox(checked, "Checkbox");
if ui.button("Open…").clicked() {
ui.close();
}
});
ui.checkbox(&mut self.checked, "Checkbox");
// Customized color SubMenuButton
let is_bright = self.color.intensity() > 0.5;
let text_color = if is_bright {
egui::Color32::BLACK
} else {
egui::Color32::WHITE
};
let mut color_button =
SubMenuButton::new(RichText::new("Background").color(text_color));
color_button.button = color_button.button.fill(self.color);
color_button.button = color_button
.button
.right_text(RichText::new(SubMenuButton::RIGHT_ARROW).color(text_color));
color_button.ui(ui, |ui| {
ui.spacing_mut().slider_width = 200.0;
color_picker_color32(ui, &mut self.color, Alpha::Opaque);
});
if ui.button("Open…").clicked() {
ui.close();
}
});
}
}
impl Default for PopupsDemo {
fn default() -> Self {
Self {
align4: RectAlign::default(),
gap: 4.0,
close_behavior: PopupCloseBehavior::CloseOnClick,
popup_open: false,
checked: false,
color: egui::Color32::RED,
}
}
}
impl crate::Demo for PopupsDemo {
fn name(&self) -> &'static str {
"\u{2755} Popups"
}
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
egui::Window::new(self.name())
.open(open)
.resizable(false)
.default_width(250.0)
.constrain(false)
.show(ctx, |ui| {
use crate::View as _;
self.ui(ui);
});
}
}
impl crate::View for PopupsDemo {
@@ -129,10 +151,10 @@ impl crate::View for PopupsDemo {
.inner;
self.apply_options(Popup::menu(&response).id(Id::new("menu")))
.show(|ui| nested_menus(ui, &mut self.checked));
.show(|ui| self.nested_menus(ui));
self.apply_options(Popup::context_menu(&response).id(Id::new("context_menu")))
.show(|ui| nested_menus(ui, &mut self.checked));
.show(|ui| self.nested_menus(ui));
if self.popup_open {
self.apply_options(Popup::from_response(&response).id(Id::new("popup")))

View File

@@ -1,4 +1,4 @@
use egui::{Image, UserData, ViewportCommand, Widget};
use egui::{Image, UserData, ViewportCommand, Widget as _};
use std::sync::Arc;
/// Showcase [`ViewportCommand::Screenshot`].
@@ -58,7 +58,7 @@ impl crate::View for Screenshot {
None
}
})
.last()
.next_back()
});
if let Some(image) = image {

View File

@@ -1,6 +1,6 @@
use egui::{
pos2, scroll_area::ScrollBarVisibility, Align, Align2, Color32, DragValue, NumExt, Rect,
ScrollArea, Sense, Slider, TextStyle, TextWrapMode, Ui, Vec2, Widget,
pos2, scroll_area::ScrollBarVisibility, Align, Align2, Color32, DragValue, NumExt as _, Rect,
ScrollArea, Sense, Slider, TextStyle, TextWrapMode, Ui, Vec2, Widget as _,
};
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]

View File

@@ -13,6 +13,7 @@ enum DemoType {
pub struct TableDemo {
demo: DemoType,
striped: bool,
overline: bool,
resizable: bool,
clickable: bool,
num_rows: usize,
@@ -28,6 +29,7 @@ impl Default for TableDemo {
Self {
demo: DemoType::Manual,
striped: true,
overline: true,
resizable: true,
clickable: true,
num_rows: 10_000,
@@ -65,6 +67,7 @@ impl crate::View for TableDemo {
ui.vertical(|ui| {
ui.horizontal(|ui| {
ui.checkbox(&mut self.striped, "Striped");
ui.checkbox(&mut self.overline, "Overline some rows");
ui.checkbox(&mut self.resizable, "Resizable columns");
ui.checkbox(&mut self.clickable, "Clickable rows");
});
@@ -212,6 +215,7 @@ impl TableDemo {
let row_height = if is_thick { 30.0 } else { 18.0 };
body.row(row_height, |mut row| {
row.set_selected(self.selection.contains(&row_index));
row.set_overline(self.overline && row_index % 7 == 3);
row.col(|ui| {
ui.label(row_index.to_string());
@@ -247,6 +251,7 @@ impl TableDemo {
};
row.set_selected(self.selection.contains(&row_index));
row.set_overline(self.overline && row_index % 7 == 3);
row.col(|ui| {
ui.label(row_index.to_string());
@@ -280,6 +285,7 @@ impl TableDemo {
};
row.set_selected(self.selection.contains(&row_index));
row.set_overline(self.overline && row_index % 7 == 3);
row.col(|ui| {
ui.label(row_index.to_string());

View File

@@ -110,7 +110,7 @@ impl crate::View for GridTest {
ui.end_row();
let mut dyn_text = String::from("O");
dyn_text.extend(std::iter::repeat('h').take(self.text_length));
dyn_text.extend(std::iter::repeat_n('h', self.text_length));
ui.label(dyn_text);
ui.label("Fifth row, second column");
ui.end_row();

View File

@@ -6,6 +6,7 @@ mod input_event_history;
mod input_test;
mod layout_test;
mod manual_layout_test;
mod svg_test;
mod tessellation_test;
mod window_resize_test;
@@ -17,5 +18,6 @@ pub use input_event_history::InputEventHistory;
pub use input_test::InputTest;
pub use layout_test::LayoutTest;
pub use manual_layout_test::ManualLayoutTest;
pub use svg_test::SvgTest;
pub use tessellation_test::TessellationTest;
pub use window_resize_test::WindowResizeTest;

View File

@@ -0,0 +1,42 @@
pub struct SvgTest {
color: egui::Color32,
}
impl Default for SvgTest {
fn default() -> Self {
Self {
color: egui::Color32::LIGHT_RED,
}
}
}
impl crate::Demo for SvgTest {
fn name(&self) -> &'static str {
"SVG Test"
}
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
egui::Window::new(self.name()).open(open).show(ctx, |ui| {
use crate::View as _;
self.ui(ui);
});
}
}
impl crate::View for SvgTest {
fn ui(&mut self, ui: &mut egui::Ui) {
let Self { color } = self;
ui.color_edit_button_srgba(color);
let img_src = egui::include_image!("../../../data/peace.svg");
// First paint a small version, sized the same as the source…
ui.add(
egui::Image::new(img_src.clone())
.fit_to_original_size(1.0)
.tint(*color),
);
// …then a big one, to make sure they are both crisp
ui.add(egui::Image::new(img_src).tint(*color));
}
}

View File

@@ -1,5 +1,5 @@
use egui::{
emath::{GuiRounding, TSTransform},
emath::{GuiRounding as _, TSTransform},
epaint::{self, RectShape},
vec2, Color32, Pos2, Rect, Sense, StrokeKind, Vec2,
};

View File

@@ -114,7 +114,7 @@ impl crate::View for TextEditDemo {
#[cfg(test)]
mod tests {
use egui::{accesskit, CentralPanel};
use egui_kittest::kittest::{Key, Queryable};
use egui_kittest::kittest::{Key, Queryable as _};
use egui_kittest::Harness;
#[test]

View File

@@ -76,7 +76,7 @@ pub fn toggle_ui(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
}
/// Here is the same code again, but a bit more compact:
#[allow(dead_code)]
#[expect(dead_code)]
fn toggle_ui_compact(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0, 1.0);
let (rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click());
@@ -121,5 +121,5 @@ pub fn toggle(on: &mut bool) -> impl egui::Widget + '_ {
}
pub fn url_to_file_source_code() -> String {
format!("https://github.com/emilk/egui/blob/master/{}", file!())
format!("https://github.com/emilk/egui/blob/main/{}", file!())
}

View File

@@ -48,7 +48,7 @@ impl Default for WidgetGallery {
}
impl WidgetGallery {
#[allow(unused_mut)] // if not chrono
#[allow(unused_mut, clippy::allow_attributes)] // if not chrono
#[inline]
pub fn with_date_button(mut self, _with_date_button: bool) -> Self {
#[cfg(feature = "chrono")]
@@ -308,7 +308,7 @@ fn doc_link_label_with_crate<'a>(
#[cfg(test)]
mod tests {
use super::*;
use crate::View;
use crate::View as _;
use egui::Vec2;
use egui_kittest::Harness;
@@ -322,7 +322,10 @@ mod tests {
let mut harness = Harness::builder()
.with_pixels_per_point(2.0)
.with_size(Vec2::new(380.0, 550.0))
.build_ui(|ui| demo.ui(ui));
.build_ui(|ui| {
egui_extras::install_image_loaders(ui.ctx());
demo.ui(ui);
});
harness.fit_contents();

View File

@@ -80,8 +80,8 @@ impl EasyMarkEditor {
} = self;
let response = if self.highlight_editor {
let mut layouter = |ui: &egui::Ui, easymark: &str, wrap_width: f32| {
let mut layout_job = highlighter.highlight(ui.style(), easymark);
let mut layouter = |ui: &egui::Ui, easymark: &dyn TextBuffer, wrap_width: f32| {
let mut layout_job = highlighter.highlight(ui.style(), easymark.as_str());
layout_job.wrap.max_width = wrap_width;
ui.fonts(|f| f.layout_job(layout_job))
};
@@ -146,7 +146,7 @@ fn shortcuts(ui: &Ui, code: &mut dyn TextBuffer, ccursor_range: &mut CCursorRang
if ui.input_mut(|i| i.consume_shortcut(&SHORTCUT_INDENT)) {
// This is a placeholder till we can indent the active line
any_change = true;
let [primary, _secondary] = ccursor_range.sorted();
let [primary, _secondary] = ccursor_range.sorted_cursors();
let advance = code.insert_text(" ", primary.index);
ccursor_range.primary.index += advance;
@@ -177,7 +177,7 @@ fn toggle_surrounding(
ccursor_range: &mut CCursorRange,
surrounding: &str,
) {
let [primary, secondary] = ccursor_range.sorted();
let [primary, secondary] = ccursor_range.sorted_cursors();
let surrounding_ccount = surrounding.chars().count();
@@ -237,7 +237,7 @@ Goals:
2. easy to learn
3. similar to markdown
[The reference parser](https://github.com/emilk/egui/blob/master/crates/egui_demo_lib/src/easy_mark/easy_mark_parser.rs) is \~250 lines of code, using only the Rust standard library. The parser uses no look-ahead or recursion.
[The reference parser](https://github.com/emilk/egui/blob/main/crates/egui_demo_lib/src/easy_mark/easy_mark_parser.rs) is \~250 lines of code, using only the Rust standard library. The parser uses no look-ahead or recursion.
There is never more than one way to accomplish the same thing, and each special character is only used for one thing. For instance `*` is used for *strong* and `-` is used for bullet lists. There is no alternative way to specify the *strong* style or getting a bullet list.

View File

@@ -35,7 +35,7 @@ macro_rules! egui_github_link_file {
};
($label: expr) => {
egui::github_link_file!(
"https://github.com/emilk/egui/blob/master/",
"https://github.com/emilk/egui/blob/main/",
egui::RichText::new($label).small()
)
};
@@ -49,7 +49,7 @@ macro_rules! egui_github_link_file_line {
};
($label: expr) => {
egui::github_link_file_line!(
"https://github.com/emilk/egui/blob/master/",
"https://github.com/emilk/egui/blob/main/",
egui::RichText::new($label).small()
)
};

View File

@@ -92,8 +92,6 @@ impl ColorTest {
ui.label("Test that vertex color times texture color is done in gamma space:");
ui.scope(|ui| {
ui.spacing_mut().item_spacing.y = 0.0; // No spacing between gradients
let tex_color = Color32::from_rgb(64, 128, 255);
let vertex_color = Color32::from_rgb(128, 196, 196);
let ground_truth = mul_color_gamma(tex_color, vertex_color);
@@ -106,6 +104,9 @@ impl ColorTest {
show_color(ui, vertex_color, color_size);
ui.label(" vertex color =");
});
ui.spacing_mut().item_spacing.y = 0.0; // No spacing between gradients
{
let g = Gradient::one_color(ground_truth);
self.vertex_gradient(ui, "Ground truth (vertices)", WHITE, &g);
@@ -129,6 +130,34 @@ impl ColorTest {
ui.separator();
ui.label("Test that blending is done in gamma space:");
ui.scope(|ui| {
let background = Color32::from_rgb(200, 60, 10);
let foreground = Color32::from_rgba_unmultiplied(108, 65, 200, 82);
let ground_truth = background.blend(foreground);
ui.horizontal(|ui| {
let color_size = ui.spacing().interact_size;
ui.label("Background:");
show_color(ui, background, color_size);
ui.label(", foreground: ");
show_color(ui, foreground, color_size);
});
ui.spacing_mut().item_spacing.y = 0.0; // No spacing between gradients
{
let g = Gradient::one_color(ground_truth);
self.vertex_gradient(ui, "Ground truth (vertices)", WHITE, &g);
self.tex_gradient(ui, "Ground truth (texture)", WHITE, &g);
}
{
let g = Gradient::one_color(foreground);
self.vertex_gradient(ui, "Vertex blending", background, &g);
self.tex_gradient(ui, "Texture blending", background, &g);
}
});
ui.separator();
// TODO(emilk): test color multiplication (image tint),
// to make sure vertex and texture color multiplication is done in linear space.
@@ -278,7 +307,10 @@ fn vertex_gradient(ui: &mut Ui, bg_fill: Color32, gradient: &Gradient) -> Respon
}
{
let n = gradient.0.len();
assert!(n >= 2);
assert!(
n >= 2,
"A gradient must have at least two colors, but this had {n}"
);
let mut mesh = Mesh::default();
for (i, &color) in gradient.0.iter().enumerate() {
let t = i as f32 / (n as f32 - 1.0);
@@ -387,10 +419,7 @@ impl TextureManager {
let height = 1;
ctx.load_texture(
"color_test_gradient",
epaint::ColorImage {
size: [width, height],
pixels,
},
epaint::ColorImage::new([width, height], pixels),
TextureOptions::LINEAR,
)
})
@@ -437,7 +466,7 @@ fn pixel_test_strokes(ui: &mut Ui) {
let thickness_points = thickness_pixels / pixels_per_point;
let num_squares = (pixels_per_point * 10.0).round().max(10.0) as u32;
let size_pixels = vec2(ui.min_size().x, num_squares as f32 + thickness_pixels * 2.0);
let size_points = size_pixels / pixels_per_point + Vec2::splat(2.0);
let size_points = size_pixels / pixels_per_point;
let (response, painter) = ui.allocate_painter(size_points, Sense::hover());
let mut cursor_pixel = Pos2::new(
@@ -565,8 +594,14 @@ fn blending_and_feathering_test(ui: &mut Ui) {
}
fn text_on_bg(ui: &mut egui::Ui, fg: Color32, bg: Color32) {
assert!(fg.is_opaque());
assert!(bg.is_opaque());
assert!(
fg.is_opaque(),
"Foreground color must be opaque, but was: {fg:?}",
);
assert!(
bg.is_opaque(),
"Background color must be opaque, but was: {bg:?}",
);
ui.horizontal(|ui| {
ui.label(

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:536fa3adb51f69fac91396b50e26b3b18e0aa8ff245e4a187087b02240839a90
size 31780
oid sha256:cbe9f58cce2466360b4b93b03afaaee36711b3017ddff1b2b56bfe49ea91a076
size 31306

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b4f807098e0bc56eaacabb76d646a76036cc66a7a6e54b1c934fa9fecb5b0170
size 26470

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c129436a0b1dbfae999adfe0dcc6f5c4e0683c4e9b9a1e52f4b7bbb85ce3a462
size 27162
oid sha256:7224afc6e728f60c28c027bf4be03d1f598dc70977274bcd32b7398d11dd36c7
size 26416

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0466198f14d15f011e16d16efcc28aeaaf80978ea4e46b5d9a1282304c192c4c
size 80907
oid sha256:5cfc3ee54a0e64fb8b72d55e9fc2079aa2517b200665684076d63b87c381cdb9
size 78704

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:629006243b61f25e48a454cc617b8e49e38985eebbfe136f3bcb0b361d204671
size 61431

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d6ba28dacacf5b6f67746fb5187b601e222fd6baf190af2248fdc98909fc17fd
size 25921
oid sha256:49b08c1fb7878d8670d96de9f9791e2db5cf7206812da1d9102c4dd1758cb803
size 25833

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8196e08717f16c5ad17d0f84a4e57e63bb5a51c8f2b171071bf983af18ec161d
size 20834
oid sha256:1e3e0330de3f68593329d2f36649127d5ac70109232c68f5c7ce310fa919fda5
size 20348

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:df029c69651ee452cc4b265828280e47ffbcafb2958d71d67a5fe38f5211afe7
size 10788
oid sha256:2882a9842f51a7c3e9642a9a3d260407e1194648f47574608822a293bd3b1d56
size 10465

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0a62d309912501be8a5de7af4f1039a2a5731b1ed76fad17527f5783a5375f42
size 133230
oid sha256:1523b8ad99267eceb65a9009ca38d99937e61c45a1115d050644f037cadfc16c
size 127794

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9870334dd6091fa684b78f487ad9a1bb39e6e8d97f987eb74a55de2d7b764f70
size 24345
oid sha256:a0b999914adab3d44c614bdf3b28abd268a4ff6162c5680b43035b3f71cb69bb
size 23999

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0c975c8b646425878b704f32198286010730746caf5d463ca8cbcfe539922816
size 99087

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bae5f410ed30ef4dba6f3b529ae20e34a26f6c15c4cafd197899cf876271f5f1
size 17828
oid sha256:57e09bcf48541af11e44ff07122f09640e0329db0c2bc7a6ecb406a3ece572ac
size 17608

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8d31533f812b2b72410b5caafea9b647d3f4cc9da3db9fcf37c332cb57d58742
size 111670

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:502790125ddd0204ea8a468c80c6f3e824adcd98f5a3f626e97f3512d31e1074
size 24516

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5fc9e2ec3253a30ac9649995b019b6b23d745dba07a327886f574a15c0e99e84
size 50082

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:68ded8dccceb3da2764243f2a554c2b4cf825fca09008d60dd520c7fbb2c5d3e
size 22445
oid sha256:641e5c7d4deccc8eb0374db4707dc356285a5c72186f9021d0d601c22bc5115f
size 21894

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c47a19d1f56fcc4c30c7e88aada2a50e038d66c1b591b4646b86c11bffb3c66f
size 46563

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3110fab8444cb41dffe8b27277fa5dafd0d335aaf13dca511bcccc8b53fb25c8
size 24046

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d55baa6e3d4af44a35ec847639c35f968b05ad907352c45b3eb09cce6cd24280
size 64357
oid sha256:116a53258be27d9c7c56538e5f83202ea731f19887fabadc0449d24fde4d80d9
size 64494

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:98f7210fa72bdb00364e3576aefca126a6f31eff52870d116ba74c167354b13b
size 32533
oid sha256:2f467edf4a84c8a98d96f168d843edb201ad2ee067dcd9d8d9ea214a02a41b1f
size 32182

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7868d662bd61d490dce9c049fca6c6e6b978255664fa709e959891bb40a7d434
size 36577
oid sha256:01705a1a49350278f524bbc5dbd47ae9da4b57ee7f6f34fb20186e1aa9b9f1d4
size 35714

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fb3d031b8f658a90cf98e7a7bc5e0d7a3b601d742e2a9469cd115e7466e06524
size 17628
oid sha256:03cb424100e99a141daeacc78036c4334d74cace3fae19bb878565ccda68457d
size 17448

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7ace9a6626446f8e29ec4c3f688e60cbeb86e79ad962044858aabe33a9c3d0e9
size 264538
oid sha256:df1e4a1e355100056713e751a8979d4201d0e4aab5513ba2f7a3e4852e1347dd
size 264340

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:17dc2a2f98d4cc52f6c6337dcc2e40f22d7310a933de91bb60576b893926193c
size 58674
oid sha256:6ed78a559488474487c0a434a941e434b22354e4374d13059076d76da93bc609
size 57051

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:22515363a812443b65cbe9060e2352e18eed04dc382fc993c33bd8a4b5ddff91
size 24817

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7d412700c156c641f0184a239198f33bd2427a1ea998a3ee07160cf0f837df94
size 35451
oid sha256:cdff6256488f3a40c65a3d73c0635377bf661c57927bce4c853b2a5f3b33274e
size 35121

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:89efd018caac097a5f9be37dcae15fc60b1475c72fc913ec9940540344e0b09f
size 23622
oid sha256:63f5c3be15164e6f008fb09b4ff37eff2af0ab361de28d1994d595789c379df5
size 23205

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:22c89f7b9b84563d6ee7db0d9a66f6b95c9034261fdffca53ae9737d70d2b376
size 183881
oid sha256:4a347875ef98ebbd606774e03baffdb317cb0246882db116fee1aa7685efbb88
size 179653

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:316c172a936f215afdcc45e7f5b32400e6acd759551adb2cc741f7121b9d83eb
size 117790
oid sha256:f0e3eeca8abb4fba632cef4621d478fb66af1a0f13e099dda9a79420cc2b6301
size 115320

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:88913690a2b225ca634e38406a6a852250019a19d9bb33a4242e77c10fe88422
size 26142
oid sha256:eb7c844f6b745f66304ad036790a5121e4827fa91569b28ffa301794aecd0c66
size 25592

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:43b8dae4a936bf56b92368fcef64ff2ce2518aabc534a77fa578730493034f0f
size 70536
oid sha256:9d27ed8292a2612b337f663bff73cd009a82f806c61f0863bf70a53fd4c281ff
size 75074

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f90d56d40004f61628e3f66cfac817c426cd18eb4b9c69ea1b3a6fe5e75e3f05
size 70354

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a307ac48abc79548c16468b3606a5df283ab2a5ac28345bd801bcc3887063414
size 66384
oid sha256:e177888e10f357f1be8ad80f7a0a33c93798c1e7c43cfe382119eeb12f21279f
size 64732

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6311be2b850b5e41ac6dadf639b00584438b56f651a3c8d75ac8f5e06c9ad6fa
size 21224
oid sha256:e177e2631414784161a5556bdd1420ce8432f9859faede1a2e6f791a02814412
size 20918

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:92b70683a685869274749d057de174896e18dae5cb67e70221c3efdb7106cdda
size 63684
oid sha256:c49c489fe1bb00512c9d08e8d8454fce786744f4ebff0bfd27dac68b7e67b815
size 62317

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3584f16229bae50cc04b31df6bf5ccf43288fd05b447b34b29f118eb7435a090
size 13103
oid sha256:c4d6a15094eee5d96a8af5c44ea9d0c962d650ee9b867344c86d1229e526dcb5
size 12822

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e67b1e676ff994cb9557939db3dca5ddd15c69d167afd96c0957a2a3b75c0fd8
size 36007
oid sha256:02abc0cbab97e572218f422f4b167957869d4e2b4b388355444c20148d998015
size 35200

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8c0ce7090ba12d849f9e3c77010503b394f3e1fce65c382738f55f7181fd7450
size 42527

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1ac48ec9f7bde9869f1b3097e9f897b5e8df96cd6159a6ded542582dc69ab32c
size 47913
oid sha256:e954bf915d562abc69269cd10a4df8fbd0e5603929e6446fefa694099e2494a4
size 47542

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:795e16389b31ad719050247eb9e736782380a83fa71b5b35b50e17812c8d9bdd
size 47886
oid sha256:1c7bd1a65b6c33eff2fe17f7af2dd731a03658abc2419f8722c0e9395b26fdef
size 47515

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a62a286e29aa0e0f949088ddefe01137535877408ba88778f61cbfe8d50c2261
size 43750
oid sha256:e89cd220a925150384b9f9987b178036ffacfe29cdb36ed688205524dbb731fd
size 43803

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9c1bc8e22aa1050a4e7d1b2abe407251e22d338c38a7e41c045a384c9139b4de
size 43895
oid sha256:b71da58f5c0178517f9e0cc97753a0a5d1653cc5d094b5a35ffe050499bcd569
size 43679

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:03ee62427611101758958adf2650a4a0eea4e023f07c9ec4ebc63425233e8a04
size 554949
oid sha256:9f6cf5b14056522d06f0cb1e56bafd7e5ab7a9033eb358748d43d748bb0ceef1
size 553177

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:82ef265f0e22649c7fcdb9556879c1a30df582bd4e97c647258b3e5acc03d112
size 771298
oid sha256:fd3bd1f64995db34a14dbc860ae8b8e269073ed7b8f10d10ce8f99b613cfc999
size 769357

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cad71b486a479eb9c5339a93f4acc3df2d0b6b188ad023b9b044be7311b0ab72
size 918775
oid sha256:f12e6145f3a1c3fda6dede3daeb0e52ed2bffb35531d823133224a477798a14a
size 907800

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dc9ed4d29f4227b9d38b477ee8f546ea8597acda56a6909ba4826891ebdbea01
size 1039263
oid sha256:05bdcfd2c34b6d7badede14f5495dce34e5e9cfe421314f40dcea15e9f865736
size 1024735

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e9bf826bee811d8af345ec1281266fc9bef6d7c3782279516984a6c75130a929
size 1130895
oid sha256:8365c89f6b823f01464a9310bab7717bf25305b335cdeecf21711c7dca9f053f
size 1140082

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9345de28f09e2891fd01db20bb0b94176ec3c89d8c2f344a6640d33e97ab5400
size 1311417
oid sha256:b38021057ec6b5bb39c41bd4afaf5e9ff38687216d52d5bba8cbf7b6fdfe9a4f
size 1291518

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5524138c3cb98aa71ef67083ad2d01813ab2394f93f9a7897f2e465ef5a1d0bc
size 46270
oid sha256:4ac90da596084a880487035b276177e98d711854143373d59860f01733b1c0cd
size 45592

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bdf06c41b69eef1eadc8b46020e6e2a7b985a54e1cf75646ca47caaaea525b95
size 88092
oid sha256:e412d424aac7b9cbdfdb8e36bd598e6cbc77183da7733c94c5f20e70699b8b4a
size 87263

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c5ca9c97cef8242ee6ff73d571479be12a8d4e9b3508b3eb6cdf93abda62f4e6
size 120314
oid sha256:222a32da21c69ee46e847e29fb05fd5e1d2de6bb7a22358549bc426f8243fdcb
size 119671

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f0481c97c34693b32575d96b1d4bc1238cbb0eb75a934661072f1b52ffee71cf
size 52171
oid sha256:d42e11f50a9522dd5ae73e8f8336bfb01493751705055a63abea3f5258f7c9c1
size 51626

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:883fdf81e51bfe6333ddcad7998458db251f9cf513c9433179061d7d086eebe0
size 55367
oid sha256:b567d4038fd73986c80d2bd12197a6df037fde043545993fa9fe4160d0af446c
size 54829

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4294949669042e009ac6825ea599dc96e33cdde25e21174b01e3ef108ad478d5
size 55944
oid sha256:fbf40a1f56a6e280002719c6556fe477c93fa7fe88d398372ed36efaa1b83a62
size 55282

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:39e5d196ddcaa213b30b0655fe29881a1551c3036c2262f84af8960f66365300
size 37207
oid sha256:33621731155ebb463fb01ea41ab20272885250efcd7d5c7683c10936b296e14d
size 36446

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f9cf9d7f1921bfc0d61a2ae31e69a98d28280e4699823de5e732cdb102aee5ac
size 37253
oid sha256:186bd8a3146ad8f1977955e3f7fa593877ad1bf1e8376d32f446c67f36a2aafe
size 36493

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:946bf96ae558ee7373b50bf11959e82b1f4d91866ec61b04b0336ae170b6f7b2
size 158553
oid sha256:ee129f0542f21e12f5aa3c2f9746e7cadd73441a04d580f57c12c1cdd40d8b07
size 153136