Skip to content

Commit

Permalink
get rid of Options, rename FieldOptions to Attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobhellermann committed Jan 21, 2021
1 parent b072035 commit af032d4
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 104 deletions.
4 changes: 2 additions & 2 deletions bevy-inspector-egui-derive/src/inspectable_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ pub fn expand_enum(derive_input: &syn::DeriveInput, data: &syn::DataEnum) -> Tok

quote! {
impl bevy_inspector_egui::Inspectable for #name {
type FieldOptions = ();
type Attributes = ();


fn ui(&mut self, ui: &mut bevy_inspector_egui::egui::Ui, options: bevy_inspector_egui::Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut bevy_inspector_egui::egui::Ui, options: Self::Attributes) {
use bevy_inspector_egui::egui;

let id = ui.make_persistent_id(stringify!(#id));
Expand Down
15 changes: 7 additions & 8 deletions bevy-inspector-egui-derive/src/inspectable_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ pub fn expand_struct(derive_input: &syn::DeriveInput, data: &syn::DataStruct) ->
};

// user specified options
let custom_options = custom_attributes.iter().fold(
quote! {let mut custom_options = <#ty as bevy_inspector_egui::Inspectable>::FieldOptions::default();},
let options = custom_attributes.iter().fold(
quote! { let mut options = <#ty as bevy_inspector_egui::Inspectable>::Attributes::default(); },
|acc,attribute| {
let assignment = match attribute {
InspectableAttribute::Assignment(name, expr) => quote!{ custom_options.#name = #expr; },
InspectableAttribute::Tag(name) => quote!{ custom_options.#name = true;}
InspectableAttribute::Assignment(name, expr) => quote!{ options.#name = #expr; },
InspectableAttribute::Tag(name) => quote!{ options.#name = true;}
};
quote! {
#acc
Expand All @@ -48,8 +48,7 @@ pub fn expand_struct(derive_input: &syn::DeriveInput, data: &syn::DataStruct) ->
);

let ui = quote! {
#custom_options
let options = bevy_inspector_egui::Options::new(custom_options);
#options
<#ty as bevy_inspector_egui::Inspectable>::ui(&mut self.#accessor, ui, options);
};

Expand All @@ -68,10 +67,10 @@ pub fn expand_struct(derive_input: &syn::DeriveInput, data: &syn::DataStruct) ->

quote! {
impl bevy_inspector_egui::Inspectable for #name {
type FieldOptions = ();
type Attributes = ();


fn ui(&mut self, ui: &mut bevy_inspector_egui::egui::Ui, options: bevy_inspector_egui::Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut bevy_inspector_egui::egui::Ui, options: Self::Attributes) {
use bevy_inspector_egui::egui;

let grid = egui::Grid::new(stringify!(#id));
Expand Down
12 changes: 6 additions & 6 deletions src/impls/bevy_impls.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
use crate::{options::NumberAttributes, Inspectable, Options};
use crate::{options::NumberAttributes, Inspectable};
use bevy::prelude::*;
use bevy_egui::egui;
use egui::Grid;

impl Inspectable for Quat {
type FieldOptions = NumberAttributes<[f32; 4]>;
type Attributes = NumberAttributes<[f32; 4]>;

fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>) {
let options = options.map(|custom| custom.map(|arr| Vec4::from(*arr)));
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes) {
let options = options.map(|arr| Vec4::from(*arr));
let mut vec4 = Vec4::from(*self);
vec4.ui(ui, options);
*self = vec4.into();
}
}

impl Inspectable for Transform {
type FieldOptions = ();
type Attributes = ();

fn ui(&mut self, ui: &mut bevy_egui::egui::Ui, _options: crate::Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut bevy_egui::egui::Ui, _options: Self::Attributes) {
let id = "asdf";
Grid::new(id).show(ui, |ui| {
ui.label("Translation");
Expand Down
63 changes: 30 additions & 33 deletions src/impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod vec;
#[allow(unreachable_pub)] // it _is_ imported, but rustc does not seem to realize that
pub use vec::Vec2dAttributes;

use crate::{Inspectable, Options};
use crate::Inspectable;
use bevy::render::color::Color;
use bevy_egui::egui;
use egui::widgets;
Expand Down Expand Up @@ -44,24 +44,24 @@ impl<T> NumberAttributes<T> {
macro_rules! impl_for_num {
($ty:ident $(default_speed=$default_speed:expr)? ) => {
impl Inspectable for $ty {
type FieldOptions = NumberAttributes<$ty>;
type Attributes = NumberAttributes<$ty>;

fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes) {
let mut widget = widgets::DragValue::$ty(self);

if !options.custom.prefix.is_empty() {
widget = widget.prefix(options.custom.prefix);
if !options.prefix.is_empty() {
widget = widget.prefix(options.prefix);
}
if !options.custom.suffix.is_empty() {
widget = widget.suffix(options.custom.suffix);
if !options.suffix.is_empty() {
widget = widget.suffix(options.suffix);
}

if options.custom.min != options.custom.max {
widget = widget.range(options.custom.min as f32..=options.custom.max as f32);
if options.min != options.max {
widget = widget.range(options.min as f32..=options.max as f32);
}

if options.custom.speed != 0.0 {
widget = widget.speed(options.custom.speed);
if options.speed != 0.0 {
widget = widget.speed(options.speed);
} $(else {
widget = widget.speed($default_speed);
})?
Expand All @@ -75,16 +75,13 @@ macro_rules! impl_for_num {
macro_rules! impl_for_num_delegate_f64 {
($ty:ty) => {
impl Inspectable for $ty {
type FieldOptions = NumberAttributes<$ty>;
type Attributes = NumberAttributes<$ty>;

fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>) {
let options_f64 = options.map(|custom| {
let mut custom = custom.map(|v| *v as f64);
if custom.speed == 0.0 {
custom.speed = 1.0;
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes) {
let mut options_f64 = options.map(|val| *val as f64);
if options_f64.speed == 0.0 {
options_f64.speed = 1.0;
}
custom
});

let mut value = *self as f64;
<f64 as Inspectable>::ui(&mut value, ui, options_f64);
Expand Down Expand Up @@ -114,10 +111,10 @@ pub struct StringAttributes {
}

impl Inspectable for String {
type FieldOptions = StringAttributes;
type Attributes = StringAttributes;

fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>) {
let widget = match options.custom.multiline {
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes) {
let widget = match options.multiline {
false => widgets::TextEdit::singleline(self),
true => widgets::TextEdit::multiline(self),
};
Expand All @@ -127,8 +124,8 @@ impl Inspectable for String {
}

impl Inspectable for bool {
type FieldOptions = ();
fn ui(&mut self, ui: &mut egui::Ui, _: Options<Self::FieldOptions>) {
type Attributes = ();
fn ui(&mut self, ui: &mut egui::Ui, _: Self::Attributes) {
ui.checkbox(self, "");
}
}
Expand All @@ -139,12 +136,12 @@ pub struct ColorAttributes {
}

impl Inspectable for Color {
type FieldOptions = ColorAttributes;
type Attributes = ColorAttributes;

fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes) {
let old: [f32; 4] = (*self).into();

if options.custom.alpha {
if options.alpha {
let mut color = egui::color::Color32::from_rgba_premultiplied(
(old[0] * u8::MAX as f32) as u8,
(old[1] * u8::MAX as f32) as u8,
Expand All @@ -166,11 +163,11 @@ impl Inspectable for Color {
impl<T> Inspectable for Vec<T>
where
T: Inspectable + Default,
T::FieldOptions: Clone,
T::Attributes: Clone,
{
type FieldOptions = <T as Inspectable>::FieldOptions;
type Attributes = <T as Inspectable>::Attributes;

fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes) {
ui.vertical(|ui| {
let mut to_delete = None;

Expand Down Expand Up @@ -200,11 +197,11 @@ where
#[cfg(feature = "nightly")]
impl<T: Inspectable, const N: usize> Inspectable for [T; N]
where
T::FieldOptions: Clone,
T::Attributes: Clone,
{
type FieldOptions = <T as Inspectable>::FieldOptions;
type Attributes = <T as Inspectable>::Attributes;

fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes) {
ui.vertical(|ui| {
for (i, val) in self.iter_mut().enumerate() {
ui.horizontal(|ui| {
Expand Down
37 changes: 15 additions & 22 deletions src/impls/vec.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::ops::RangeInclusive;

use crate::{Inspectable, Options};
use crate::Inspectable;
use bevy::math::{Vec2, Vec3, Vec4};
use bevy_egui::egui::{self, containers, Rect};
use egui::{Pos2, Sense, Widget};
Expand All @@ -22,14 +22,14 @@ impl Default for Vec2dAttributes {
}

impl Inspectable for Vec2 {
type FieldOptions = Vec2dAttributes;
type Attributes = Vec2dAttributes;

fn ui(&mut self, ui: &mut bevy_egui::egui::Ui, options: Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut bevy_egui::egui::Ui, options: Self::Attributes) {
let mut frame = containers::Frame::dark_canvas(&ui.style());
frame.margin = egui::Vec2::zero();

frame.show(ui, |ui| {
let range = options.custom.min..=options.custom.max;
let range = options.min..=options.max;
let widget = PointSelect::new(self, range, 80.0);
ui.add(widget);
});
Expand Down Expand Up @@ -103,40 +103,33 @@ impl Widget for PointSelect<'_> {
}

impl Inspectable for Vec3 {
type FieldOptions = NumberAttributes<Vec3>;
type Attributes = NumberAttributes<Vec3>;

fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes) {
ui.wrap(|ui| {
ui.style_mut().spacing.item_spacing = egui::Vec2::new(4.0, 0.);

ui.columns(3, |ui| {
self.x
.ui(&mut ui[0], options.map(|opt| opt.map(|vec| vec.x)));
self.y
.ui(&mut ui[1], options.map(|opt| opt.map(|vec| vec.x)));
self.z
.ui(&mut ui[2], options.map(|opt| opt.map(|vec| vec.x)));
self.x.ui(&mut ui[0], options.map(|vec| vec.x));
self.y.ui(&mut ui[1], options.map(|vec| vec.x));
self.z.ui(&mut ui[2], options.map(|vec| vec.x));
});
});
}
}

impl Inspectable for Vec4 {
type FieldOptions = NumberAttributes<Vec4>;
type Attributes = NumberAttributes<Vec4>;

fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>) {
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes) {
ui.wrap(|ui| {
ui.style_mut().spacing.item_spacing = egui::Vec2::new(4.0, 0.);

ui.columns(4, |ui| {
self.x
.ui(&mut ui[0], options.map(|opt| opt.map(|vec| vec.x)));
self.y
.ui(&mut ui[1], options.map(|opt| opt.map(|vec| vec.x)));
self.z
.ui(&mut ui[2], options.map(|opt| opt.map(|vec| vec.x)));
self.w
.ui(&mut ui[3], options.map(|opt| opt.map(|vec| vec.x)));
self.x.ui(&mut ui[0], options.map(|vec| vec.x));
self.y.ui(&mut ui[1], options.map(|vec| vec.x));
self.z.ui(&mut ui[2], options.map(|vec| vec.x));
self.w.ui(&mut ui[3], options.map(|vec| vec.x));
});
});
}
Expand Down
39 changes: 8 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,45 +52,22 @@ pub mod options {
pub use crate::impls::*;
}

#[non_exhaustive]
#[derive(Default, Debug, Clone)]
/// This type is passed to the [`Inspectable::ui`](Inspectable::ui) method
/// to give access to the attributes specified in the `#[derive(Inspectable)]`.
/// For an example of defining custom attributes, see the [docs of Inspectable](Inspectable::FieldOptions).
pub struct Options<T> {
/// The user defined options
pub custom: T,
}
impl<T: Default> Options<T> {
/// Create new options
pub fn new(custom: T) -> Self {
Options { custom }
}
}
impl<T> Options<T> {
fn map<U>(&self, f: impl Fn(&T) -> U) -> Options<U> {
Options {
custom: f(&self.custom),
}
}
}

/// This trait describes how a struct should be displayed.
/// It can be derived for structs and enums, see the [crate-level docs](index.html) for how to do that.
pub trait Inspectable {
/// The `FieldOptions` associated type specifies what attributes can be passed to a field.
/// The `Attributes` associated type specifies what attributes can be passed to a field.
/// See the following snippet for an example:
/// ```rust
/// # use bevy_inspector_egui::{egui, Inspectable, Options};
/// # use bevy_inspector_egui::{egui, Inspectable};
/// struct MyCustomType;
/// # #[derive(Default)]
/// struct MyWidgetOptions { a: f32, b: Option<String> }
/// struct MyWidgetAttributes { a: f32, b: Option<String> }
///
/// impl Inspectable for MyCustomType {
/// type FieldOptions = MyWidgetOptions;
/// type Attributes = MyWidgetAttributes;
///
/// fn ui(&mut self, _: &mut egui::Ui, options: Options<MyWidgetOptions>) {
/// println!("a = {}, b = {:?}", options.custom.a, options.custom.b);
/// fn ui(&mut self, _: &mut egui::Ui, options: MyWidgetAttributes) {
/// println!("a = {}, b = {:?}", options.a, options.b);
/// }
/// }
///
Expand All @@ -102,8 +79,8 @@ pub trait Inspectable {
/// value: MyCustomType,
/// }
/// ```
type FieldOptions: Default;
type Attributes: Default;

/// This methods is responsible for building the egui ui.
fn ui(&mut self, ui: &mut egui::Ui, options: Options<Self::FieldOptions>);
fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes);
}
4 changes: 2 additions & 2 deletions src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::marker::PhantomData;
use bevy::prelude::*;
use bevy_egui::{egui, EguiContext, EguiPlugin};

use crate::{Inspectable, Options};
use crate::Inspectable;

#[derive(Default)]
#[allow(missing_debug_implementations)]
Expand Down Expand Up @@ -37,6 +37,6 @@ where
egui::Window::new("Inspector")
.resizable(false)
.show(ctx, |ui| {
data.ui(ui, Options::default());
data.ui(ui, T::Attributes::default());
});
}

0 comments on commit af032d4

Please sign in to comment.