Skip to content

Commit 1f2e386

Browse files
authored
Enhance properties pane UI with improved layout and styling for entity selection and component display (#211)
* Enhance properties pane UI with improved layout and styling for entity selection and component display * use bevy_reflect to start inspecting Component values. could use some guidance on this! * fix clippy
1 parent 5dcfd5e commit 1f2e386

File tree

1 file changed

+84
-37
lines changed
  • bevy_editor_panes/bevy_properties_pane/src

1 file changed

+84
-37
lines changed

bevy_editor_panes/bevy_properties_pane/src/lib.rs

Lines changed: 84 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,18 @@ fn update_properties_pane(
5151
fn properties_pane(selected_entity: &SelectedEntity, world: &World) -> Template {
5252
match selected_entity.0 {
5353
Some(selected_entity) => component_list(selected_entity, world),
54-
None => template! {(
55-
Text("Select an entity to inspect".into()),
56-
TextFont::from_font_size(14.0),
57-
);},
54+
None => template! {
55+
Node {
56+
flex_direction: FlexDirection::Column,
57+
..Default::default()
58+
} => [
59+
(
60+
Text("Select an entity to inspect".into()),
61+
TextFont::from_font_size(14.0),
62+
);
63+
];
64+
65+
},
5866
}
5967
}
6068

@@ -69,55 +77,94 @@ fn component_list(entity: Entity, world: &World) -> Template {
6977
.type_id()
7078
.and_then(|type_id| type_registry.get_type_info(type_id));
7179

80+
// Get the reflected component value from the world
81+
let reflect: Option<&dyn Reflect> = component_info.type_id().and_then(|type_id| {
82+
let registration = type_registry.get(type_id)?;
83+
let reflect_component = registration.data::<ReflectComponent>()?;
84+
let entity_ref = world.get_entity(entity);
85+
reflect_component.reflect(entity_ref.unwrap())
86+
});
87+
7288
template! {
7389
Node {
7490
flex_direction: FlexDirection::Column,
91+
margin: UiRect::all(Val::Px(4.0)),
92+
7593
..Default::default()
7694
} => [
77-
(
78-
Text(name.into()),
79-
TextFont::from_font_size(12.0),
80-
);
81-
@{ component(type_info) };
95+
// Collapsible header for the component
96+
Node {
97+
flex_direction: FlexDirection::Row,
98+
align_items: AlignItems::Center,
99+
..Default::default()
100+
} => [
101+
(
102+
Text(format!("⯆ {name}")),
103+
TextFont::from_font_size(14.0),
104+
TextColor(Color::WHITE),
105+
);
106+
];
107+
// Component fields
108+
@{ match reflect {
109+
Some(reflect) => component(type_info, reflect),
110+
None => template! {
111+
Node {
112+
flex_direction: FlexDirection::Row,
113+
..Default::default()
114+
} => [
115+
(
116+
Text("<unavailable>".into()),
117+
TextFont::from_font_size(10.0),
118+
TextColor(Color::srgb(1.0, 0.0, 0.0)),
119+
);
120+
];
121+
},
122+
} };
82123
];
83124
}
84125
})
85126
.collect()
86127
}
87128

88-
fn component(type_info: Option<&TypeInfo>) -> Template {
129+
fn component(type_info: Option<&TypeInfo>, reflect: &dyn Reflect) -> Template {
89130
match type_info {
90-
Some(type_info) => reflected_component(type_info),
91-
None => template! {(
92-
Text("Reflect not implemented".into()),
93-
TextFont::from_font_size(10.0),
94-
TextColor(tailwind::NEUTRAL_300.into()),
95-
);},
131+
Some(TypeInfo::Struct(struct_info)) => reflected_struct(struct_info, reflect),
132+
Some(TypeInfo::TupleStruct(tuple_struct_info)) => reflected_tuple_struct(tuple_struct_info),
133+
Some(TypeInfo::Enum(enum_info)) => reflected_enum(enum_info),
134+
_ => template! {},
96135
}
97136
}
98-
99-
fn reflected_component(type_info: &TypeInfo) -> Template {
100-
match type_info {
101-
TypeInfo::Struct(struct_info) => reflected_struct(struct_info),
102-
TypeInfo::TupleStruct(tuple_struct_info) => reflected_tuple_struct(tuple_struct_info),
103-
TypeInfo::Tuple(_tuple_info) => todo!(),
104-
TypeInfo::List(_list_info) => todo!(),
105-
TypeInfo::Array(_array_info) => todo!(),
106-
TypeInfo::Map(_map_info) => todo!(),
107-
TypeInfo::Set(_set_info) => todo!(),
108-
TypeInfo::Enum(enum_info) => reflected_enum(enum_info),
109-
TypeInfo::Opaque(_opaque_info) => todo!(),
110-
}
111-
}
112-
113-
fn reflected_struct(struct_info: &StructInfo) -> Template {
137+
fn reflected_struct(struct_info: &StructInfo, reflect: &dyn Reflect) -> Template {
114138
let fields = struct_info
115139
.iter()
116-
.flat_map(|field| {
117-
template! {(
118-
Text(field.name().into()),
119-
TextFont::from_font_size(10.0),
120-
);}
140+
.enumerate()
141+
.flat_map(|(i, field)| {
142+
let value = reflect
143+
.reflect_ref()
144+
.as_struct()
145+
.map(|s| s.field_at(i))
146+
.map(|v| format!("{v:?}"))
147+
.unwrap_or("<unavailable>".to_string());
148+
149+
template! {
150+
Node {
151+
flex_direction: FlexDirection::Row,
152+
margin: UiRect::vertical(Val::Px(2.0)),
153+
..Default::default()
154+
} => [
155+
(
156+
Text(field.name().to_string()),
157+
TextFont::from_font_size(12.0),
158+
TextColor(Color::srgb(0.8, 0.8, 0.8)),
159+
);
160+
(
161+
// Value (use reflection to get value as string)
162+
Text(value),
163+
TextFont::from_font_size(10.0),
164+
TextColor(Color::WHITE),
165+
);
166+
];
167+
}
121168
})
122169
.collect::<Template>();
123170

0 commit comments

Comments
 (0)