mirror of
https://github.com/Noratrieb/game-wip-dontplay.git
synced 2026-01-14 11:45:01 +01:00
vendor egui_inspect
This commit is contained in:
parent
48386a6cf2
commit
16be9061d9
11 changed files with 3364 additions and 3 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -73,7 +73,6 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "egui-inspect"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/crumblingstatue/egui-inspect.git#77b02370966aad6be6eeb94ce88ae9268986fc0d"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"egui-inspect-derive",
|
||||
|
|
@ -82,7 +81,6 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "egui-inspect-derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/crumblingstatue/egui-inspect.git#77b02370966aad6be6eeb94ce88ae9268986fc0d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ edition = "2021"
|
|||
egui = "0.21.0"
|
||||
|
||||
[dependencies.egui-inspect]
|
||||
git = "https://github.com/crumblingstatue/egui-inspect.git"
|
||||
path = "./egui_inspect"
|
||||
|
||||
#[profile.dev]
|
||||
#incremental = false # Buggy on latest rustc nightly, keeps ICEing
|
||||
|
|
|
|||
1
egui_inspect/.gitignore
vendored
Normal file
1
egui_inspect/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
2679
egui_inspect/Cargo.lock
generated
Normal file
2679
egui_inspect/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
17
egui_inspect/Cargo.toml
Normal file
17
egui_inspect/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "egui-inspect"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
derive = ["egui-inspect-derive"]
|
||||
default = ["derive"]
|
||||
|
||||
[dependencies]
|
||||
egui = "0.21.0"
|
||||
egui-inspect-derive = { path = "egui-inspect-derive", optional = true}
|
||||
|
||||
[workspace]
|
||||
members = ["egui-inspect-derive", "testbed"]
|
||||
14
egui_inspect/egui-inspect-derive/Cargo.toml
Normal file
14
egui_inspect/egui-inspect-derive/Cargo.toml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "egui-inspect-derive"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = "2.0.15"
|
||||
quote = "1.0.26"
|
||||
proc-macro2 = "1.0.56"
|
||||
106
egui_inspect/egui-inspect-derive/src/lib.rs
Normal file
106
egui_inspect/egui-inspect-derive/src/lib.rs
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, Attribute, Data, DeriveInput, Member};
|
||||
|
||||
enum FieldInspectKind {
|
||||
/// Auto-inspected (it is assumed that the field implements Inspect)
|
||||
Auto,
|
||||
/// A function named by the token stream is called to inspect the field.
|
||||
/// The function takes (thing: &mut T, ui: &mut Ui, id_source: u64)
|
||||
WithFn(syn::Ident),
|
||||
/// Not visited, left alone.
|
||||
/// Useful when you want to skip a field that doesn't implement Inspect.
|
||||
Opaque,
|
||||
}
|
||||
|
||||
fn inspect_kind(attrs: &[Attribute]) -> FieldInspectKind {
|
||||
for attr in attrs {
|
||||
if attr.path().is_ident("opaque") {
|
||||
return FieldInspectKind::Opaque;
|
||||
} else if attr.path().is_ident("inspect_with") {
|
||||
let fun: syn::Ident = attr.parse_args().expect("Failed to parse ident");
|
||||
return FieldInspectKind::WithFn(fun);
|
||||
}
|
||||
}
|
||||
FieldInspectKind::Auto
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Inspect, attributes(opaque, inspect_with))]
|
||||
pub fn derive_inspect(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
let ty_ident = input.ident;
|
||||
let ts = match input.data {
|
||||
Data::Struct(s) => {
|
||||
let mut exprs = Vec::new();
|
||||
for (i, f) in s.fields.iter().enumerate() {
|
||||
let memb = match &f.ident {
|
||||
Some(ident) => Member::from(ident.clone()),
|
||||
None => Member::from(i),
|
||||
};
|
||||
match inspect_kind(&f.attrs) {
|
||||
FieldInspectKind::Auto => {
|
||||
exprs.push(quote! {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.add(::egui::Label::new(stringify!(#f)).sense(::egui::Sense::click())).clicked() {
|
||||
ui.output_mut(|o| o.copied_text = format!("{:?}", self.#memb));
|
||||
}
|
||||
::egui_inspect::Inspect::inspect_mut(&mut self.#memb, ui, #i as u64)
|
||||
});
|
||||
});
|
||||
}
|
||||
FieldInspectKind::Opaque => {
|
||||
exprs.push(quote! {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(concat!(stringify!(#memb), " <opaque>"));
|
||||
});
|
||||
});
|
||||
}
|
||||
FieldInspectKind::WithFn(fun) => {
|
||||
exprs.push(quote! {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(stringify!(#memb));
|
||||
#fun(&mut self.#memb, ui, #i as u64)
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
quote! {
|
||||
::egui::CollapsingHeader::new(stringify!(#ty_ident)).id_source(id_source).show(ui, |ui| {
|
||||
#(#exprs)*
|
||||
});
|
||||
}
|
||||
}
|
||||
Data::Enum(e) => {
|
||||
let mut sel_name_match_exprs = Vec::new();
|
||||
let mut selectable_value_exprs = Vec::new();
|
||||
for var in &e.variants {
|
||||
let name = &var.ident;
|
||||
sel_name_match_exprs.push(quote! {Self::#name => stringify!(#name)});
|
||||
selectable_value_exprs
|
||||
.push(quote! {ui.selectable_value(self, Self::#name, stringify!(#name))});
|
||||
}
|
||||
quote! {
|
||||
let sel_text = match self {
|
||||
#(#sel_name_match_exprs,)*
|
||||
};
|
||||
::egui::ComboBox::new(id_source, stringify!(#ty_ident)).selected_text(sel_text).show_ui(ui, |ui| {
|
||||
#(#selectable_value_exprs;)*
|
||||
});
|
||||
}
|
||||
}
|
||||
Data::Union(_) => panic!("Unions are not supported"),
|
||||
};
|
||||
let (intro_generics, forward_generics, where_clauses) = input.generics.split_for_impl();
|
||||
let expanded = quote! {
|
||||
impl #intro_generics ::egui_inspect::Inspect for #ty_ident #forward_generics #where_clauses {
|
||||
fn inspect(&self, ui: &mut ::egui::Ui, id_source: u64) {
|
||||
|
||||
}
|
||||
fn inspect_mut(&mut self, ui: &mut ::egui::Ui, id_source: u64) {
|
||||
#ts
|
||||
}
|
||||
}
|
||||
};
|
||||
proc_macro::TokenStream::from(expanded)
|
||||
}
|
||||
385
egui_inspect/src/lib.rs
Normal file
385
egui_inspect/src/lib.rs
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
use egui::Ui;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
ffi::OsString,
|
||||
fmt::Debug,
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
pub use egui_inspect_derive as derive;
|
||||
|
||||
pub trait Inspect: Debug {
|
||||
fn inspect(&self, ui: &mut Ui, id_source: u64);
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
|
||||
self.inspect(ui, id_source);
|
||||
}
|
||||
}
|
||||
|
||||
impl Inspect for String {
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, _id_source: u64) {
|
||||
ui.text_edit_singleline(self);
|
||||
}
|
||||
|
||||
fn inspect(&self, ui: &mut Ui, _id_source: u64) {
|
||||
ui.label(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Inspect> Inspect for Vec<T> {
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, mut id_source: u64) {
|
||||
ui.inspect_iter_with_mut(
|
||||
&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) {
|
||||
egui::CollapsingHeader::new(format!("Vec [{}]", self.len()))
|
||||
.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> {
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
|
||||
match self {
|
||||
None => {
|
||||
ui.label("None");
|
||||
}
|
||||
Some(t) => {
|
||||
t.inspect_mut(ui, id_source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn inspect(&self, ui: &mut Ui, id_source: u64) {
|
||||
match self {
|
||||
None => {
|
||||
ui.label("None");
|
||||
}
|
||||
Some(t) => {
|
||||
t.inspect(ui, id_source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Inspect for OsString {
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
|
||||
self.inspect(ui, id_source);
|
||||
}
|
||||
|
||||
fn inspect(&self, ui: &mut Ui, _id_source: u64) {
|
||||
ui.label(format!("(OsString) {}", self.to_string_lossy()));
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Inspect> Inspect for HashSet<T> {
|
||||
fn inspect(&self, ui: &mut Ui, mut id_source: u64) {
|
||||
egui::CollapsingHeader::new("HashSet")
|
||||
.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 {
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
|
||||
(*self).inspect_mut(ui, id_source)
|
||||
}
|
||||
|
||||
fn inspect(&self, ui: &mut Ui, id_source: u64) {
|
||||
(**self).inspect(ui, id_source)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Inspect, const N: usize> Inspect for [T; N] {
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
|
||||
egui::CollapsingHeader::new(format!("array[{}]", self.len()))
|
||||
.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) {
|
||||
egui::CollapsingHeader::new(format!("array[{}]", self.len()))
|
||||
.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> {
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
|
||||
egui::CollapsingHeader::new(format!("HashMap [{}]", self.len()))
|
||||
.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) {
|
||||
egui::CollapsingHeader::new(format!("HashMap [{}]", self.len()))
|
||||
.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 {
|
||||
fn inspect(&self, ui: &mut Ui, _id_source: u64) {
|
||||
if ui
|
||||
.add(egui::Label::new(*self).sense(egui::Sense::click()))
|
||||
.clicked()
|
||||
{
|
||||
ui.output_mut(|o| o.copied_text = self.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Inspect for bool {
|
||||
fn inspect(&self, ui: &mut Ui, _id_source: u64) {
|
||||
let mut value = *self;
|
||||
ui.checkbox(&mut value, "");
|
||||
}
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, _id_source: u64) {
|
||||
ui.checkbox(self, "");
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_num_inspect {
|
||||
($($ty:ty),*) => {
|
||||
$(impl Inspect for $ty {
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, _id_source: u64) {
|
||||
ui.add(egui::DragValue::new(self));
|
||||
}
|
||||
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<T, U> Inspect for (T, U)
|
||||
where
|
||||
T: Inspect,
|
||||
U: Inspect,
|
||||
{
|
||||
fn inspect_mut(&mut self, ui: &mut Ui, id_source: u64) {
|
||||
self.0.inspect_mut(ui, id_source);
|
||||
self.1.inspect_mut(ui, id_source);
|
||||
}
|
||||
|
||||
fn inspect(&self, ui: &mut Ui, id_source: u64) {
|
||||
self.0.inspect(ui, id_source);
|
||||
self.1.inspect(ui, id_source);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait UiExt {
|
||||
fn inspect<T: Inspect>(&mut self, what: &T, id_source: &mut u64);
|
||||
fn inspect_iter_with<'a, I, T, F>(
|
||||
&mut self,
|
||||
title: &str,
|
||||
into_iter: I,
|
||||
id_source: &mut u64,
|
||||
fun: F,
|
||||
) where
|
||||
I: IntoIterator<Item = &'a T>,
|
||||
T: 'a,
|
||||
F: FnMut(&mut Ui, usize, &T, &mut u64);
|
||||
fn inspect_iter_with_mut<'a, I, T, F>(
|
||||
&mut self,
|
||||
title: &str,
|
||||
into_iter: I,
|
||||
id_source: &mut u64,
|
||||
fun: F,
|
||||
) where
|
||||
I: IntoIterator<Item = &'a mut T>,
|
||||
T: 'a,
|
||||
F: FnMut(&mut Ui, usize, &mut T, &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);
|
||||
}
|
||||
|
||||
macro_rules! inspect_iter_with_body {
|
||||
($self:expr, $title:expr, $into_iter:expr, $id_source:expr, $fun:expr) => {
|
||||
egui::CollapsingHeader::new($title)
|
||||
.id_source(*$id_source)
|
||||
.show($self, |ui| {
|
||||
for (i, item) in $into_iter.into_iter().enumerate() {
|
||||
$fun(ui, i, item, $id_source);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
impl UiExt for Ui {
|
||||
fn inspect<T: Inspect>(&mut self, what: &T, id_source: &mut u64) {
|
||||
what.inspect(self, *id_source);
|
||||
*id_source += 1;
|
||||
}
|
||||
fn inspect_iter_with<'a, I, T, F>(
|
||||
&mut self,
|
||||
title: &str,
|
||||
into_iter: I,
|
||||
id_source: &mut u64,
|
||||
mut fun: F,
|
||||
) where
|
||||
I: IntoIterator<Item = &'a T>,
|
||||
T: 'a,
|
||||
F: FnMut(&mut Ui, usize, &T, &mut u64),
|
||||
{
|
||||
inspect_iter_with_body!(self, title, into_iter, id_source, fun);
|
||||
}
|
||||
fn inspect_iter_with_mut<'a, I, T, F>(
|
||||
&mut self,
|
||||
title: &str,
|
||||
into_iter: I,
|
||||
id_source: &mut u64,
|
||||
mut fun: F,
|
||||
) where
|
||||
I: IntoIterator<Item = &'a mut T>,
|
||||
T: 'a,
|
||||
F: FnMut(&mut Ui, usize, &mut T, &mut u64),
|
||||
{
|
||||
inspect_iter_with_body!(self, title, into_iter, id_source, fun);
|
||||
}
|
||||
fn inspect_mut<T: Inspect>(&mut self, what: &mut T, id_source: &mut u64) {
|
||||
what.inspect_mut(self, *id_source);
|
||||
*id_source += 1;
|
||||
}
|
||||
fn property<T: Inspect>(&mut self, name: &str, what: &mut T, id_source: &mut u64) {
|
||||
self.horizontal(|ui| {
|
||||
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> {
|
||||
fn inspect(&self, ui: &mut Ui, _id_source: u64) {
|
||||
ui.label("PhantomData");
|
||||
}
|
||||
}
|
||||
|
||||
impl Inspect for () {
|
||||
fn inspect(&self, ui: &mut Ui, _id_source: u64) {
|
||||
ui.label("()");
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! inspect {(
|
||||
$ui:expr, $($rest:tt)*
|
||||
) => ({
|
||||
let mut id_source = 0;
|
||||
$crate::inspect_helper! { $ui id_source $($rest)* }
|
||||
})}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! inspect_helper {
|
||||
($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::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)*
|
||||
})?
|
||||
);
|
||||
}
|
||||
14
egui_inspect/testbed/Cargo.toml
Normal file
14
egui_inspect/testbed/Cargo.toml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "testbed"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies.egui-inspect]
|
||||
path = ".."
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8.5"
|
||||
eframe = "0.21.3"
|
||||
egui = "0.21.0"
|
||||
146
egui_inspect/testbed/src/main.rs
Normal file
146
egui_inspect/testbed/src/main.rs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use eframe::{egui, App, Frame, NativeOptions};
|
||||
use egui_inspect::inspect;
|
||||
use egui_inspect::{derive::Inspect, Inspect};
|
||||
use rand::{distributions::Alphanumeric, prelude::SliceRandom, thread_rng, Rng};
|
||||
|
||||
struct Testbed {
|
||||
entities: Vec<GameEntity>,
|
||||
some_string: String,
|
||||
}
|
||||
|
||||
#[derive(Inspect, Debug)]
|
||||
struct GameEntity {
|
||||
name: String,
|
||||
position: Vector2,
|
||||
hp: i32,
|
||||
godmode: bool,
|
||||
dir: Dir,
|
||||
#[opaque]
|
||||
#[allow(dead_code)]
|
||||
something_opaque: MyOpaque,
|
||||
#[inspect_with(custom_inspect)]
|
||||
custom: MyOpaque,
|
||||
tuple: TupleStruct,
|
||||
generic: Generic<String>,
|
||||
phantom: PhantomData<NonInspect>,
|
||||
unit: (),
|
||||
}
|
||||
|
||||
struct NonInspect;
|
||||
|
||||
#[derive(Inspect, Debug)]
|
||||
struct TupleStruct(u32);
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct MyOpaque {
|
||||
field1: i32,
|
||||
field2: String,
|
||||
field3: f32,
|
||||
}
|
||||
|
||||
#[derive(Inspect, Debug)]
|
||||
struct Generic<T: Inspect> {
|
||||
field: T,
|
||||
}
|
||||
|
||||
fn custom_inspect(o: &mut MyOpaque, ui: &mut egui::Ui, _id_source: u64) {
|
||||
ui.collapsing("MyOpaque", |ui| {
|
||||
inspect! {
|
||||
ui,
|
||||
"field 1": o.field1,
|
||||
"field 2": o.field2,
|
||||
"field 3": o.field3
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Inspect, Clone, Copy, PartialEq, Eq, Debug)]
|
||||
enum Dir {
|
||||
North,
|
||||
East,
|
||||
South,
|
||||
West,
|
||||
}
|
||||
|
||||
impl GameEntity {
|
||||
fn rand() -> Self {
|
||||
let mut rng = rand::thread_rng();
|
||||
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)]
|
||||
struct Vector2 {
|
||||
x: f32,
|
||||
y: f32,
|
||||
}
|
||||
|
||||
impl Vector2 {
|
||||
fn rand() -> Self {
|
||||
let mut rng = thread_rng();
|
||||
Self {
|
||||
x: rng.gen(),
|
||||
y: rng.gen(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Testbed {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
entities: (0..100).map(|_| GameEntity::rand()).collect(),
|
||||
some_string: "Hello world!".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl App for Testbed {
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
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() {
|
||||
eframe::run_native(
|
||||
"egui-inspect testbed",
|
||||
NativeOptions::default(),
|
||||
Box::new(|_cc| Box::<Testbed>::default()),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
use egui_inspect::Inspect;
|
||||
|
||||
extern crate alloc;
|
||||
mod tiles;
|
||||
|
||||
pub(crate) struct App {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue