vendorreduce

This commit is contained in:
nora 2023-04-18 14:35:47 +02:00
parent 16be9061d9
commit 99ef22ac1f
3 changed files with 53 additions and 297 deletions

View file

@ -1,7 +1,6 @@
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::quote; use quote::quote;
use syn::{parse_macro_input, Attribute, Data, DeriveInput, Member}; use syn::{parse_macro_input, Attribute, Data, DeriveInput, Member};
enum FieldInspectKind { enum FieldInspectKind {
/// Auto-inspected (it is assumed that the field implements Inspect) /// Auto-inspected (it is assumed that the field implements Inspect)
Auto, Auto,

View file

@ -1,254 +1,112 @@
use egui::Ui; use egui::Ui;
#[cfg(feature = "derive")]
pub use egui_inspect_derive as derive;
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
ffi::OsString, ffi::OsString,
fmt::Debug, fmt::Debug,
marker::PhantomData, marker::PhantomData,
}; };
#[cfg(feature = "derive")]
pub use egui_inspect_derive as derive;
pub trait Inspect: Debug { pub trait Inspect: Debug {
fn inspect(&self, ui: &mut Ui, id_source: u64); fn inspect(&self, ui: &mut Ui, id_source: u64);
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
self.inspect(ui, id_source); loop {}
} }
} }
impl Inspect for String { impl Inspect for String {
fn inspect_mut(&mut self, ui: &mut Ui, _id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, _id_source: u64) {
ui.text_edit_singleline(self); loop {}
} }
fn inspect(&self, ui: &mut Ui, _id_source: u64) { fn inspect(&self, ui: &mut Ui, _id_source: u64) {
ui.label(self); loop {}
} }
} }
impl<T: Inspect> Inspect for Vec<T> { impl<T: Inspect> Inspect for Vec<T> {
fn inspect_mut(&mut self, ui: &mut Ui, mut id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, mut id_source: u64) {
ui.inspect_iter_with_mut( loop {}
&format!("Vec [{}]", self.len()),
self,
&mut id_source,
|ui, i, item, _id_source| {
ui.horizontal(|ui| {
if ui
.add(egui::Label::new(i.to_string()).sense(egui::Sense::click()))
.clicked()
{
ui.output_mut(|o| o.copied_text = format!("{:?}", item));
}
item.inspect_mut(ui, i as u64);
});
},
);
} }
fn inspect(&self, ui: &mut Ui, id_source: u64) { fn inspect(&self, ui: &mut Ui, id_source: u64) {
egui::CollapsingHeader::new(format!("Vec [{}]", self.len())) loop {}
.id_source(id_source)
.show(ui, |ui| {
for (i, item) in self.iter().enumerate() {
ui.horizontal(|ui| {
if ui
.add(egui::Label::new(i.to_string()).sense(egui::Sense::click()))
.clicked()
{
ui.output_mut(|o| o.copied_text = format!("{:?}", item));
}
item.inspect(ui, i as u64);
});
}
});
} }
} }
impl<T: Inspect> Inspect for Option<T> { impl<T: Inspect> Inspect for Option<T> {
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
match self { loop {}
None => {
ui.label("None");
}
Some(t) => {
t.inspect_mut(ui, id_source);
}
}
} }
fn inspect(&self, ui: &mut Ui, id_source: u64) { fn inspect(&self, ui: &mut Ui, id_source: u64) {
match self { loop {}
None => {
ui.label("None");
}
Some(t) => {
t.inspect(ui, id_source);
}
}
} }
} }
impl Inspect for OsString { impl Inspect for OsString {
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
self.inspect(ui, id_source); loop {}
} }
fn inspect(&self, ui: &mut Ui, _id_source: u64) { fn inspect(&self, ui: &mut Ui, _id_source: u64) {
ui.label(format!("(OsString) {}", self.to_string_lossy())); loop {}
} }
} }
impl<T: Inspect> Inspect for HashSet<T> { impl<T: Inspect> Inspect for HashSet<T> {
fn inspect(&self, ui: &mut Ui, mut id_source: u64) { fn inspect(&self, ui: &mut Ui, mut id_source: u64) {
egui::CollapsingHeader::new("HashSet") loop {}
.id_source(id_source)
.show(ui, |ui| {
for item in self.iter() {
ui.inspect(item, &mut id_source);
}
});
} }
} }
impl<T: Inspect> Inspect for &mut T { impl<T: Inspect> Inspect for &mut T {
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
(*self).inspect_mut(ui, id_source) loop {}
} }
fn inspect(&self, ui: &mut Ui, id_source: u64) { fn inspect(&self, ui: &mut Ui, id_source: u64) {
(**self).inspect(ui, id_source) loop {}
} }
} }
impl<T: Inspect, const N: usize> Inspect for [T; N] { impl<T: Inspect, const N: usize> Inspect for [T; N] {
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
egui::CollapsingHeader::new(format!("array[{}]", self.len())) loop {}
.id_source(id_source)
.show(ui, |ui| {
for (i, item) in self.iter_mut().enumerate() {
ui.horizontal(|ui| {
if ui
.add(egui::Label::new(i.to_string()).sense(egui::Sense::click()))
.clicked()
{
ui.output_mut(|o| o.copied_text = format!("{:?}", item));
}
item.inspect_mut(ui, i as u64);
});
}
});
} }
fn inspect(&self, ui: &mut Ui, id_source: u64) { fn inspect(&self, ui: &mut Ui, id_source: u64) {
egui::CollapsingHeader::new(format!("array[{}]", self.len())) loop {}
.id_source(id_source)
.show(ui, |ui| {
for (i, item) in self.iter().enumerate() {
ui.horizontal(|ui| {
if ui
.add(egui::Label::new(i.to_string()).sense(egui::Sense::click()))
.clicked()
{
ui.output_mut(|o| o.copied_text = format!("{:?}", item));
}
item.inspect(ui, i as u64);
});
}
});
} }
} }
impl<K: Debug, V: Inspect, S> Inspect for HashMap<K, V, S> { impl<K: Debug, V: Inspect, S> Inspect for HashMap<K, V, S> {
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
egui::CollapsingHeader::new(format!("HashMap [{}]", self.len())) loop {}
.id_source(id_source)
.show(ui, |ui| {
for (i, (k, v)) in self.iter_mut().enumerate() {
ui.horizontal(|ui| {
if ui
.add(egui::Label::new(format!("{:?}", k)).sense(egui::Sense::click()))
.clicked()
{
ui.output_mut(|o| o.copied_text = format!("{:?}", v));
}
v.inspect_mut(ui, i as u64);
});
}
});
} }
fn inspect(&self, ui: &mut Ui, id_source: u64) { fn inspect(&self, ui: &mut Ui, id_source: u64) {
egui::CollapsingHeader::new(format!("HashMap [{}]", self.len())) loop {}
.id_source(id_source)
.show(ui, |ui| {
for (i, (k, v)) in self.iter().enumerate() {
ui.horizontal(|ui| {
if ui
.add(egui::Label::new(format!("{:?}", k)).sense(egui::Sense::click()))
.clicked()
{
ui.output_mut(|o| o.copied_text = format!("{:?}", v));
}
v.inspect(ui, i as u64);
});
}
});
} }
} }
impl<'a> Inspect for &'a str { impl<'a> Inspect for &'a str {
fn inspect(&self, ui: &mut Ui, _id_source: u64) { fn inspect(&self, ui: &mut Ui, _id_source: u64) {
if ui loop {}
.add(egui::Label::new(*self).sense(egui::Sense::click()))
.clicked()
{
ui.output_mut(|o| o.copied_text = self.to_string())
}
} }
} }
impl Inspect for bool { impl Inspect for bool {
fn inspect(&self, ui: &mut Ui, _id_source: u64) { fn inspect(&self, ui: &mut Ui, _id_source: u64) {
let mut value = *self; loop {}
ui.checkbox(&mut value, "");
} }
fn inspect_mut(&mut self, ui: &mut Ui, _id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, _id_source: u64) {
ui.checkbox(self, ""); loop {}
} }
} }
macro_rules! impl_num_inspect { macro_rules! impl_num_inspect {
($($ty:ty),*) => { ($($ty:ty),*) => {
$(impl Inspect for $ty { $(impl Inspect for $ty { fn inspect_mut(& mut self, ui : & mut Ui, _id_source :
fn inspect_mut(&mut self, ui: &mut Ui, _id_source: u64) { u64) { ui.add(egui::DragValue::new(self)); } fn inspect(& self, ui : & mut Ui,
ui.add(egui::DragValue::new(self)); _id_source : u64) { ui.label(self.to_string()); } })*
}
fn inspect(&self, ui: &mut Ui, _id_source: u64) {
ui.label(self.to_string());
}
})*
}; };
} }
impl_num_inspect!(i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, usize, isize); impl_num_inspect!(i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, usize, isize);
impl<T, U> Inspect for (T, U) impl<T, U> Inspect for (T, U)
where where
T: Inspect, T: Inspect,
U: Inspect, U: Inspect,
{ {
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) { fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
self.0.inspect_mut(ui, id_source); loop {}
self.1.inspect_mut(ui, id_source);
} }
fn inspect(&self, ui: &mut Ui, id_source: u64) { fn inspect(&self, ui: &mut Ui, id_source: u64) {
self.0.inspect(ui, id_source); loop {}
self.1.inspect(ui, id_source);
} }
} }
pub trait UiExt { pub trait UiExt {
fn inspect<T: Inspect>(&mut self, what: &T, id_source: &mut u64); fn inspect<T: Inspect>(&mut self, what: &T, id_source: &mut u64);
fn inspect_iter_with<'a, I, T, F>( fn inspect_iter_with<'a, I, T, F>(
@ -274,7 +132,6 @@ pub trait UiExt {
fn inspect_mut<T: Inspect>(&mut self, what: &mut T, id_source: &mut u64); fn inspect_mut<T: Inspect>(&mut self, what: &mut T, id_source: &mut u64);
fn property<T: Inspect>(&mut self, name: &str, what: &mut T, id_source: &mut u64); fn property<T: Inspect>(&mut self, name: &str, what: &mut T, id_source: &mut u64);
} }
macro_rules! inspect_iter_with_body { macro_rules! inspect_iter_with_body {
($self:expr, $title:expr, $into_iter:expr, $id_source:expr, $fun:expr) => { ($self:expr, $title:expr, $into_iter:expr, $id_source:expr, $fun:expr) => {
egui::CollapsingHeader::new($title) egui::CollapsingHeader::new($title)
@ -286,11 +143,9 @@ macro_rules! inspect_iter_with_body {
}); });
}; };
} }
impl UiExt for Ui { impl UiExt for Ui {
fn inspect<T: Inspect>(&mut self, what: &T, id_source: &mut u64) { fn inspect<T: Inspect>(&mut self, what: &T, id_source: &mut u64) {
what.inspect(self, *id_source); loop {}
*id_source += 1;
} }
fn inspect_iter_with<'a, I, T, F>( fn inspect_iter_with<'a, I, T, F>(
&mut self, &mut self,
@ -303,7 +158,7 @@ impl UiExt for Ui {
T: 'a, T: 'a,
F: FnMut(&mut Ui, usize, &T, &mut u64), F: FnMut(&mut Ui, usize, &T, &mut u64),
{ {
inspect_iter_with_body!(self, title, into_iter, id_source, fun); loop {}
} }
fn inspect_iter_with_mut<'a, I, T, F>( fn inspect_iter_with_mut<'a, I, T, F>(
&mut self, &mut self,
@ -316,70 +171,40 @@ impl UiExt for Ui {
T: 'a, T: 'a,
F: FnMut(&mut Ui, usize, &mut T, &mut u64), F: FnMut(&mut Ui, usize, &mut T, &mut u64),
{ {
inspect_iter_with_body!(self, title, into_iter, id_source, fun); loop {}
} }
fn inspect_mut<T: Inspect>(&mut self, what: &mut T, id_source: &mut u64) { fn inspect_mut<T: Inspect>(&mut self, what: &mut T, id_source: &mut u64) {
what.inspect_mut(self, *id_source); loop {}
*id_source += 1;
} }
fn property<T: Inspect>(&mut self, name: &str, what: &mut T, id_source: &mut u64) { fn property<T: Inspect>(&mut self, name: &str, what: &mut T, id_source: &mut u64) {
self.horizontal(|ui| { loop {}
if ui
.add(egui::Label::new(name).sense(egui::Sense::click()))
.clicked()
{
ui.output_mut(|o| o.copied_text = format!("{:?}", what));
}
ui.inspect_mut(what, id_source);
});
} }
} }
impl<T> Inspect for PhantomData<T> { impl<T> Inspect for PhantomData<T> {
fn inspect(&self, ui: &mut Ui, _id_source: u64) { fn inspect(&self, ui: &mut Ui, _id_source: u64) {
ui.label("PhantomData"); loop {}
} }
} }
impl Inspect for () { impl Inspect for () {
fn inspect(&self, ui: &mut Ui, _id_source: u64) { fn inspect(&self, ui: &mut Ui, _id_source: u64) {
ui.label("()"); loop {}
} }
} }
#[macro_export] #[macro_export]
macro_rules! inspect {( macro_rules! inspect {
$ui:expr, $($rest:tt)* ($ui:expr, $($rest:tt)*) => {
) => ({ { let mut id_source = 0; $crate ::inspect_helper! { $ui id_source $($rest)* } }
let mut id_source = 0; };
$crate::inspect_helper! { $ui id_source $($rest)* } }
})}
#[macro_export] #[macro_export]
macro_rules! inspect_helper { macro_rules! inspect_helper {
($ui:tt $id_source:tt) => (); ($ui:tt $id_source:tt) => {};
($ui:tt $id_source:tt $name:literal : $arg:expr $(, $($rest:tt)*)?) => {
( $crate ::UiExt::property($ui, $name, & mut $arg, & mut $id_source); $($crate
$ui:tt $id_source:tt ::inspect_helper! { $ui $id_source $($rest)* })?
$name:literal : $arg:expr $(, $($rest:tt)* )? };
) => ( ($ui:tt $id_source:tt $arg:expr $(, $($rest:tt)*)?) => {
$crate::UiExt::property( $crate ::UiExt::property($ui, ::core::stringify!($arg), & mut $arg, & mut
$ui, $name, &mut $arg, &mut $id_source $id_source); $($crate ::inspect_helper! { $ui $id_source $($rest)* })?
); };
$($crate::inspect_helper! {
$ui $id_source $($rest)*
})?
);
(
$ui:tt $id_source:tt
$arg:expr $(, $($rest:tt)* )?
) => (
$crate::UiExt::property(
$ui, ::core::stringify!($arg), &mut $arg, &mut $id_source
);
$($crate::inspect_helper! {
$ui $id_source $($rest)*
})?
);
} }

View file

@ -1,16 +1,13 @@
use std::fmt::Debug; use std::fmt::Debug;
use std::marker::PhantomData; use std::marker::PhantomData;
use eframe::{egui, App, Frame, NativeOptions}; use eframe::{egui, App, Frame, NativeOptions};
use egui_inspect::inspect; use egui_inspect::inspect;
use egui_inspect::{derive::Inspect, Inspect}; use egui_inspect::{derive::Inspect, Inspect};
use rand::{distributions::Alphanumeric, prelude::SliceRandom, thread_rng, Rng}; use rand::{distributions::Alphanumeric, prelude::SliceRandom, thread_rng, Rng};
struct Testbed { struct Testbed {
entities: Vec<GameEntity>, entities: Vec<GameEntity>,
some_string: String, some_string: String,
} }
#[derive(Inspect, Debug)] #[derive(Inspect, Debug)]
struct GameEntity { struct GameEntity {
name: String, name: String,
@ -28,35 +25,22 @@ struct GameEntity {
phantom: PhantomData<NonInspect>, phantom: PhantomData<NonInspect>,
unit: (), unit: (),
} }
struct NonInspect; struct NonInspect;
#[derive(Inspect, Debug)] #[derive(Inspect, Debug)]
struct TupleStruct(u32); struct TupleStruct(u32);
#[derive(Default, Debug)] #[derive(Default, Debug)]
struct MyOpaque { struct MyOpaque {
field1: i32, field1: i32,
field2: String, field2: String,
field3: f32, field3: f32,
} }
#[derive(Inspect, Debug)] #[derive(Inspect, Debug)]
struct Generic<T: Inspect> { struct Generic<T: Inspect> {
field: T, field: T,
} }
fn custom_inspect(o: &mut MyOpaque, ui: &mut egui::Ui, _id_source: u64) { fn custom_inspect(o: &mut MyOpaque, ui: &mut egui::Ui, _id_source: u64) {
ui.collapsing("MyOpaque", |ui| { loop {}
inspect! {
ui,
"field 1": o.field1,
"field 2": o.field2,
"field 3": o.field3
}
});
} }
#[derive(Inspect, Clone, Copy, PartialEq, Eq, Debug)] #[derive(Inspect, Clone, Copy, PartialEq, Eq, Debug)]
enum Dir { enum Dir {
North, North,
@ -64,83 +48,31 @@ enum Dir {
South, South,
West, West,
} }
impl GameEntity { impl GameEntity {
fn rand() -> Self { fn rand() -> Self {
let mut rng = rand::thread_rng(); loop {}
let name_len = rng.gen_range(3..24);
Self {
name: (&mut rng)
.sample_iter(&Alphanumeric)
.take(name_len)
.map(char::from)
.collect(),
position: Vector2::rand(),
hp: rng.gen_range(0..100),
godmode: rng.gen(),
dir: *[Dir::North, Dir::East, Dir::South, Dir::West]
.choose(&mut rng)
.unwrap(),
something_opaque: MyOpaque::default(),
custom: MyOpaque::default(),
tuple: TupleStruct(42),
generic: Generic {
field: String::new(),
},
phantom: PhantomData,
unit: (),
}
} }
} }
#[derive(Inspect, Debug)] #[derive(Inspect, Debug)]
struct Vector2 { struct Vector2 {
x: f32, x: f32,
y: f32, y: f32,
} }
impl Vector2 { impl Vector2 {
fn rand() -> Self { fn rand() -> Self {
let mut rng = thread_rng(); loop {}
Self {
x: rng.gen(),
y: rng.gen(),
}
} }
} }
impl Default for Testbed { impl Default for Testbed {
fn default() -> Self { fn default() -> Self {
Self { loop {}
entities: (0..100).map(|_| GameEntity::rand()).collect(),
some_string: "Hello world!".into(),
}
} }
} }
impl App for Testbed { impl App for Testbed {
fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) { fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) {
egui::CentralPanel::default().show(ctx, |ui| { loop {}
egui::ScrollArea::vertical().show(ui, |ui| {
inspect! {
ui,
self.some_string,
self.some_string.len(),
self.entities
}
})
});
// Resize the native window to be just the size we need it to be:
frame.set_window_size(ctx.used_size());
} }
} }
fn main() { fn main() {
eframe::run_native( loop {}
"egui-inspect testbed",
NativeOptions::default(),
Box::new(|_cc| Box::<Testbed>::default()),
)
.unwrap();
} }