@@ -9,6 +9,7 @@ use bevy::{
99 scene2:: { CommandsSpawnScene , Scene , SceneList , bsn} ,
1010} ;
1111use bevy_editor_core:: { prelude:: * , selection:: common_conditions:: primary_selection_changed} ;
12+ use bevy_editor_styles:: Theme ;
1213use bevy_pane_layout:: prelude:: * ;
1314
1415/// Plugin for the editor properties pane.
@@ -18,9 +19,9 @@ impl Plugin for PropertiesPanePlugin {
1819 fn build ( & self , app : & mut App ) {
1920 app. register_pane ( "Properties" , setup_pane) . add_systems (
2021 Update ,
21- update_properties_pane. run_if (
22+ ( update_properties_pane. run_if (
2223 primary_selection_changed. or ( any_match_filter :: < Added < PropertiesPaneBody > > ) ,
23- ) ,
24+ ) , ) ,
2425 ) ;
2526 }
2627}
@@ -49,31 +50,46 @@ fn setup_pane(pane: In<PaneStructure>, mut commands: Commands) {
4950fn update_properties_pane (
5051 pane_bodies : Query < Entity , With < PropertiesPaneBody > > ,
5152 selection : Res < EditorSelection > ,
53+ theme : Res < Theme > ,
5254 world : & World ,
5355 mut commands : Commands ,
5456) {
5557 for pane_body in & pane_bodies {
5658 commands. entity ( pane_body) . despawn_children ( ) ;
5759 commands
58- . spawn_scene ( properties_pane ( & selection, world) )
60+ . spawn_scene ( properties_pane ( & selection, & theme , world) )
5961 . insert ( ChildOf ( pane_body) ) ;
6062 }
6163}
6264
63- fn properties_pane ( selection : & EditorSelection , world : & World ) -> impl Scene {
65+ fn properties_pane ( selection : & EditorSelection , theme : & Theme , world : & World ) -> impl Scene {
6466 match selection. primary ( ) {
65- Some ( selection) => bsn ! { Node { flex_direction: FlexDirection :: Column } [
66- { component_list( selection, world) }
67+ Some ( selection) => bsn ! {
68+ Node {
69+ flex_direction: FlexDirection :: Column ,
70+ padding: UiRect :: all( Val :: Px ( 8.0 ) ) ,
71+ row_gap: Val :: Px ( 6.0 )
72+ } [
73+ { component_list( selection, theme, world) }
6774 ] }
6875 . boxed_scene ( ) ,
6976 None => bsn ! {
70- ( Text ( "Select an entity to inspect" ) ThemedText )
77+ Node {
78+ flex_direction: FlexDirection :: Column ,
79+ justify_content: JustifyContent :: Center ,
80+ align_items: AlignItems :: Center ,
81+ padding: UiRect :: all( Val :: Px ( 24.0 ) )
82+ } [
83+ Text ( "Select an entity to inspect" )
84+ TextFont :: from_font_size( 14.0 )
85+ TextColor ( Color :: srgb( 0.514 , 0.514 , 0.522 ) ) ,
86+ ]
7187 }
7288 . boxed_scene ( ) ,
7389 }
7490}
7591
76- fn component_list ( entity : Entity , world : & World ) -> impl SceneList {
92+ fn component_list ( entity : Entity , theme : & Theme , world : & World ) -> impl SceneList {
7793 let type_registry = world. resource :: < AppTypeRegistry > ( ) . read ( ) ;
7894 world
7995 . inspect_entity ( entity)
@@ -98,72 +114,116 @@ fn component_list(entity: Entity, world: &World) -> impl SceneList {
98114 bsn ! {
99115 Node {
100116 flex_direction: FlexDirection :: Column ,
101- margin: UiRect :: all( Val :: Px ( 4.0 ) ) ,
102- } [
117+ margin: UiRect :: bottom( Val :: Px ( 6.0 ) ) ,
118+ border: UiRect :: all( Val :: Px ( 1.0 ) ) ,
119+ padding: UiRect :: all( Val :: Px ( 0.0 ) )
120+ }
121+ // CSS: #2A2A2E - Component background
122+ BackgroundColor ( Color :: srgb( 0.165 , 0.165 , 0.180 ) )
123+ // CSS: #414142 - Border color
124+ BorderColor :: all( Color :: srgb( 0.255 , 0.255 , 0.259 ) )
125+ BorderRadius :: all( Val :: Px ( 5.0 ) )
126+ [
127+ // Component header - CSS styling
103128 Node {
104129 flex_direction: FlexDirection :: Row ,
130+ justify_content: JustifyContent :: SpaceBetween ,
105131 align_items: AlignItems :: Center ,
106- } [
107- TextFont :: from_font_size( 14.0 )
108- Text ( { format!( "{name}" ) } )
109- TextColor ( Color :: WHITE )
132+ padding: UiRect :: all( Val :: Px ( 8.0 ) ) ,
133+ height: Val :: Px ( 26.0 )
134+ }
135+ // CSS: #36373B - Header background
136+ BackgroundColor ( Color :: srgb( 0.212 , 0.216 , 0.231 ) )
137+ BorderRadius :: top( Val :: Px ( 5.0 ) )
138+ [
139+ Node {
140+ flex_direction: FlexDirection :: Row ,
141+ align_items: AlignItems :: Center ,
142+ column_gap: Val :: Px ( 5.0 )
143+ } [
144+ Text ( "▼" )
145+ TextFont :: from_font_size( 12.0 )
146+ // CSS: #C4C4C4 - Chevron color
147+ TextColor ( Color :: srgb( 0.769 , 0.769 , 0.769 ) ) ,
148+
149+ Text ( { format!( "{name}" ) } )
150+ TextFont :: from_font_size( 12.0 )
151+ // CSS: #DCDCDC - Component name
152+ TextColor ( Color :: srgb( 0.863 , 0.863 , 0.863 ) ) ,
153+ ] ,
154+
155+ Text ( "⋯" )
156+ TextFont :: from_font_size( 12.0 )
157+ // CSS: #C4C4C4 - Menu dots
158+ TextColor ( Color :: srgb( 0.769 , 0.769 , 0.769 ) ) ,
110159 ] ,
111160 // Component fields
112161 ( { match reflect {
113- Some ( reflect) => component( type_info, reflect) . boxed_scene( ) ,
162+ Some ( reflect) => component( type_info, reflect, theme ) . boxed_scene( ) ,
114163 None => bsn! {
115164 Node {
116165 flex_direction: FlexDirection :: Row ,
166+ padding: UiRect :: all( Val :: Px ( 8.0 ) )
117167 } [
118- Text ( "<unavailable>" )
119- TextFont :: from_font_size( 10 .0)
120- TextColor ( Color :: srgb( 1.0 , 0.0 , 0.0 ) )
168+ Text ( "<reflection unavailable>" )
169+ TextFont :: from_font_size( 11 .0)
170+ TextColor ( Color :: srgb( 0.514 , 0.514 , 0.522 ) ) ,
121171 ]
122172 } . boxed_scene( ) ,
123- } } )
173+ } } ) ,
124174 ]
125175 }
126176 } )
127177 . collect :: < Vec < _ > > ( )
128178}
129179
130- fn component ( type_info : Option < & TypeInfo > , reflect : & dyn Reflect ) -> impl Scene {
180+ fn component ( type_info : Option < & TypeInfo > , reflect : & dyn Reflect , theme : & Theme ) -> impl Scene {
131181 match type_info {
132- Some ( TypeInfo :: Struct ( info) ) => reflected_struct ( info, reflect) . boxed_scene ( ) ,
133- Some ( TypeInfo :: TupleStruct ( info) ) => reflected_tuple_struct ( info) . boxed_scene ( ) ,
134- Some ( TypeInfo :: Enum ( info) ) => reflected_enum ( info) . boxed_scene ( ) ,
182+ Some ( TypeInfo :: Struct ( info) ) => reflected_struct ( info, reflect, theme ) . boxed_scene ( ) ,
183+ Some ( TypeInfo :: TupleStruct ( info) ) => reflected_tuple_struct ( info, theme ) . boxed_scene ( ) ,
184+ Some ( TypeInfo :: Enum ( info) ) => reflected_enum ( info, theme ) . boxed_scene ( ) ,
135185 _ => bsn ! { } . boxed_scene ( ) ,
136186 }
137187}
138- fn reflected_struct ( struct_info : & StructInfo , reflect : & dyn Reflect ) -> impl Scene {
188+ fn reflected_struct ( struct_info : & StructInfo , reflect : & dyn Reflect , _theme : & Theme ) -> impl Scene {
139189 let fields = struct_info
140190 . iter ( )
141191 . enumerate ( )
142192 . map ( |( i, field) | {
143- let valuee = reflect
193+ let field_reflect = reflect
144194 . reflect_ref ( )
145195 . as_struct ( )
146- . map ( |s| s. field_at ( i) )
147- . map ( |v| format ! ( "{v:?}" ) )
148- . unwrap_or ( "<unavailable>" . to_string ( ) ) ;
196+ . ok ( )
197+ . and_then ( |s| s. field_at ( i) ) ;
149198
150199 let field_name = field. name ( ) ;
200+
201+ let value_string = field_reflect
202+ . map ( |v| format ! ( "{v:?}" ) )
203+ . unwrap_or_else ( || "<unavailable>" . to_string ( ) ) ;
204+
151205 bsn ! {
152206 Node {
153207 flex_direction: FlexDirection :: Row ,
154208 margin: UiRect :: vertical( Val :: Px ( 2.0 ) ) ,
155- } [
156- (
157- Text ( field_name)
158- TextFont :: from_font_size( 12.0 )
159- TextColor ( Color :: srgb( 0.8 , 0.8 , 0.8 ) )
160- ) ,
161- (
162- // Value (use reflection to get value as string)
163- Text ( { valuee. clone( ) } )
164- TextFont :: from_font_size( 10.0 )
165- TextColor ( Color :: WHITE )
166- ) ,
209+ padding: UiRect :: all( Val :: Px ( 5.0 ) ) ,
210+ justify_content: JustifyContent :: SpaceBetween ,
211+ align_items: AlignItems :: Center ,
212+ min_height: Val :: Px ( 22.0 )
213+ }
214+ // CSS: #36373B - Field background
215+ BackgroundColor ( Color :: srgb( 0.212 , 0.216 , 0.231 ) )
216+ BorderRadius :: all( Val :: Px ( 3.0 ) )
217+ [
218+ Text ( field_name)
219+ TextFont :: from_font_size( 12.0 )
220+ // CSS: #DADADA - Field labels
221+ TextColor ( Color :: srgb( 0.855 , 0.855 , 0.855 ) ) ,
222+
223+ Text ( { value_string. clone( ) } )
224+ TextFont :: from_font_size( 12.0 )
225+ // CSS: #C2C2C2 - Field values
226+ TextColor ( Color :: srgb( 0.761 , 0.761 , 0.761 ) ) ,
167227 ]
168228 }
169229 } )
@@ -172,11 +232,13 @@ fn reflected_struct(struct_info: &StructInfo, reflect: &dyn Reflect) -> impl Sce
172232 bsn ! {
173233 Node {
174234 flex_direction: FlexDirection :: Column ,
235+ padding: UiRect :: all( Val :: Px ( 7.0 ) ) ,
236+ row_gap: Val :: Px ( 4.0 )
175237 } [ { fields} ]
176238 }
177239}
178240
179- fn reflected_tuple_struct ( tuple_struct_info : & TupleStructInfo ) -> impl Scene {
241+ fn reflected_tuple_struct ( tuple_struct_info : & TupleStructInfo , _theme : & Theme ) -> impl Scene {
180242 let fields = tuple_struct_info
181243 . iter ( )
182244 . map ( |_field| {
@@ -189,12 +251,12 @@ fn reflected_tuple_struct(tuple_struct_info: &TupleStructInfo) -> impl Scene {
189251
190252 bsn ! {
191253 Node {
192- flex_direction: FlexDirection :: Column ,
254+ flex_direction: FlexDirection :: Column
193255 } [ { fields} ]
194256 }
195257}
196258
197- fn reflected_enum ( enum_info : & EnumInfo ) -> impl Scene {
259+ fn reflected_enum ( enum_info : & EnumInfo , _theme : & Theme ) -> impl Scene {
198260 let variants = enum_info
199261 . iter ( )
200262 . map ( |variant| {
0 commit comments