bevy-inspector-egui icon indicating copy to clipboard operation
bevy-inspector-egui copied to clipboard

How can I inspect my Player component?

Open igortavtib opened this issue 1 year ago • 7 comments

Hi! I have a player component with a direction and is_moving properties:

#[derive(Component)]
pub struct Player {
    direction: Direction,
    is_moving: bool,
}

enum Direction {
    Up,
    Down,
    Left,
    Right,
}

But when trying to use the inspector I can't watch to player direction or is_moving propertires. What should I do?

igortavtib avatar Aug 29 '22 18:08 igortavtib

I have a very similar situation with trying to inspect a component with an enum field. The compiler says that I must implement bevy::reflect::Reflect on the enum, which is frankly annoying (it's just an enum! shouldn't it be the same as an i32?). There's got to be a solution with less boilerplate, right?

njelly avatar Sep 02 '22 14:09 njelly

The inspector somehow needs to know how to display these types. For the world inspector, there are two options:

  1. Derive Reflect for the Player and Direction types, and call app.register_type::<Player>().register_type::<Direction>();.
  2. Derive Inspectable for the types and register them in the InspectableRegistry.

it's just an enum! shouldn't it be the same as an i32?

In the inspector I want to display a dropdown of the values "Up", "Down", "Left" and "Right", for that to work I need to know what kind of variants the enum has and what their names are. Reflect provides exactly that information. Without it, the inspector just looks at an arbitrary component and knows that it is 2 bytes large, but has no way to interpret that data.

jakobhellermann avatar Sep 02 '22 16:09 jakobhellermann

I see. Thanks for the explanation!

njelly avatar Sep 02 '22 16:09 njelly

@jakobhellermann is there an example of implementing an enum so that it shows up in the world inspector? I suppose similar to how the depth_calculation field on the Camera component is rendered. My issue is that implementing bevy::reflect::Reflect requires many methods and functions, and since I'm new to rust and bevy I'm not sure exactly what I should return for each of them.

There is an example in this repo in enum.rs, but this isn't what I'm looking for.

njelly avatar Sep 02 '22 16:09 njelly

@jakobhellermann is there an example of implementing an enum so that it shows up in the world inspector? I suppose similar to how the depth_calculation field on the Camera component is rendered. My issue is that implementing bevy::reflect::Reflect requires many methods and functions, and since I'm new to rust and bevy I'm not sure exactly what I should return for each of them.

There is an example in this repo in enum.rs, but this isn't what I'm looking for.

The Reflect trait is meant to be derived, not manually implemented (which is very tedious). So

#[derive(Reflect)]
enum Direction {
    Up,
    Down,
    Left,
    Right,
}

should in theory work. The problem is, I think reflect reflect for enums was only recently implemented, and wasn't released in bevy 0.8. So this solution will only work in ~3 Months when bevy 0.9 releases.

Until then, you can use the alternative method of implementing Inspectable:

#[derive(Component, Inspectable)]
pub struct Player {
    direction: Direction,
    is_moving: bool,
}

#[derive(Inspectable)]
enum Direction {
    Up,
    Down,
    Left,
    Right,
}

use bevy_inspector_egui::prelude::*; // this imports the RegisterInspectable trait that adds the `app.register_inspectable` method
fn main() {
  App::new()
    .register_inspectable::<Player>()
    .register_inspectable::<Direction>()
    .run();

jakobhellermann avatar Sep 02 '22 16:09 jakobhellermann

Fantastic! Thank you, I've gotten it to work in 0.8 (at least for my needs).

Here's some of the relevant code:

#[derive(Clone, Copy, Inspectable, PartialEq, Reflect)]
pub enum CardinalDirection4 {
    None,
    East,
    South,
    West,
    North,
}
#[derive(Component, Default, Inspectable, Reflect)]
#[reflect(Component)]
pub struct Unit {
    pub facing: CardinalDirection4,
    pub input_move: CardinalDirection4,
    pub input_aim: f32, // 2D rotation
}
impl Plugin for DebugPlugin {
    fn build(&self, app: &mut App) {
        if cfg!(debug_assertions) {
            app.add_plugin(WorldInspectorPlugin::new())
                .register_inspectable::<Unit>()
                .register_type::<SpriteAnimation>();
        }
    }
}

And my world inspector now looks like this:

Screen Shot 2022-09-02 at 11 07 57 AM

njelly avatar Sep 02 '22 17:09 njelly

Thanks for all the explanation!

igortavtib avatar Sep 04 '22 22:09 igortavtib

I think this can be closed now.

For what its worth, on 0.16 you just have to derive Reflect and call .register_type.

jakobhellermann avatar Jan 05 '23 20:01 jakobhellermann