2
2
//!
3
3
//! Data can be viewed and modified in real-time, with changes being reflected in the application.
4
4
5
- use bevy:: { color:: palettes:: tailwind, prelude:: * , reflect:: * } ;
6
- use bevy_editor_core:: selection:: SelectedEntity ;
7
- use bevy_i_cant_believe_its_not_bsn:: { Template , TemplateEntityCommandsExt , template} ;
8
- use bevy_pane_layout:: prelude:: { PaneAppExt , PaneStructure } ;
5
+ use bevy:: {
6
+ feathers:: theme:: ThemedText ,
7
+ prelude:: * ,
8
+ reflect:: * ,
9
+ scene2:: { CommandsSpawnScene , Scene , SceneList , bsn} ,
10
+ } ;
11
+ use bevy_editor_core:: prelude:: * ;
12
+ use bevy_pane_layout:: prelude:: * ;
9
13
10
14
/// Plugin for the editor properties pane.
11
15
pub struct PropertiesPanePlugin ;
12
16
13
17
impl Plugin for PropertiesPanePlugin {
14
18
fn build ( & self , app : & mut App ) {
15
- app. register_pane ( "Properties" , setup_pane)
16
- . add_systems ( PostUpdate , update_properties_pane) ;
19
+ app. register_pane ( "Properties" , setup_pane) . add_systems (
20
+ Update ,
21
+ update_properties_pane. run_if (
22
+ resource_changed :: < SelectedEntity >
23
+ . or ( any_match_filter :: < Added < PropertiesPaneBody > > ) ,
24
+ ) ,
25
+ ) ;
17
26
}
18
27
}
19
28
20
29
/// Root UI node of the properties pane.
21
- #[ derive( Component ) ]
22
- struct PropertiesPaneRoot ;
30
+ #[ derive( Component , Default , Clone ) ]
31
+ struct PropertiesPaneBody ;
23
32
24
33
fn setup_pane ( pane : In < PaneStructure > , mut commands : Commands ) {
25
- commands. entity ( pane. content ) . insert ( (
26
- PropertiesPaneRoot ,
27
- Node {
28
- flex_direction : FlexDirection :: Column ,
29
- flex_grow : 1.0 ,
30
- column_gap : Val :: Px ( 4.0 ) ,
31
- padding : UiRect :: all ( Val :: Px ( 8.0 ) ) ,
32
- ..Default :: default ( )
33
- } ,
34
- BackgroundColor ( tailwind:: NEUTRAL_600 . into ( ) ) ,
35
- ) ) ;
34
+ // Remove the existing structure
35
+ commands. entity ( pane. area ) . despawn ( ) ;
36
+
37
+ commands
38
+ . spawn_scene ( bsn ! {
39
+ : editor_pane [
40
+ : editor_pane_header [
41
+ ( Text ( "Properties" ) ThemedText ) ,
42
+ ] ,
43
+ : editor_pane_body
44
+ PropertiesPaneBody
45
+ ]
46
+ } )
47
+ . insert ( Node :: default ( ) )
48
+ . insert ( ChildOf ( pane. root ) ) ;
36
49
}
37
50
38
51
fn update_properties_pane (
39
- panes : Query < Entity , With < PropertiesPaneRoot > > ,
52
+ pane_bodies : Query < Entity , With < PropertiesPaneBody > > ,
40
53
selected_entity : Res < SelectedEntity > ,
41
54
world : & World ,
42
55
mut commands : Commands ,
43
56
) {
44
- for pane in & panes {
57
+ for pane_body in & pane_bodies {
58
+ commands. entity ( pane_body) . despawn_children ( ) ;
45
59
commands
46
- . entity ( pane)
47
- . build_children ( properties_pane ( & selected_entity, world) ) ;
60
+ . spawn_scene ( properties_pane ( & selected_entity, world) )
61
+ . insert ( Node :: default ( ) )
62
+ . insert ( ChildOf ( pane_body) ) ;
48
63
}
49
64
}
50
65
51
- fn properties_pane ( selected_entity : & SelectedEntity , world : & World ) -> Template {
66
+ fn properties_pane ( selected_entity : & SelectedEntity , world : & World ) -> impl Scene {
52
67
match selected_entity. 0 {
53
- Some ( selected_entity) => component_list ( selected_entity, world) ,
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
- } ,
68
+ Some ( selected_entity) => bsn ! { Node { flex_direction: FlexDirection :: Column } [
69
+ { component_list( selected_entity, world) }
70
+ ] }
71
+ . boxed_scene ( ) ,
72
+ None => bsn ! {
73
+ ( Text ( "Select an entity to inspect" ) ThemedText )
74
+ }
75
+ . boxed_scene ( ) ,
66
76
}
67
77
}
68
78
69
- fn component_list ( entity : Entity , world : & World ) -> Template {
79
+ fn component_list ( entity : Entity , world : & World ) -> impl SceneList {
70
80
let type_registry = world. resource :: < AppTypeRegistry > ( ) . read ( ) ;
71
81
world
72
82
. inspect_entity ( entity)
73
83
. unwrap ( )
74
- . flat_map ( |component_info| {
84
+ . map ( |component_info| {
75
85
let type_info = component_info
76
86
. type_id ( )
77
87
. and_then ( |type_id| type_registry. get_type_info ( type_id) ) ;
@@ -88,131 +98,120 @@ fn component_list(entity: Entity, world: &World) -> Template {
88
98
reflect_component. reflect ( entity_ref. unwrap ( ) )
89
99
} ) ;
90
100
91
- template ! {
101
+ bsn ! {
92
102
Node {
93
103
flex_direction: FlexDirection :: Column ,
94
104
margin: UiRect :: all( Val :: Px ( 4.0 ) ) ,
95
-
96
- ..Default :: default ( )
97
- } => [
98
- // Collapsible header for the component
105
+ } [
99
106
Node {
100
107
flex_direction: FlexDirection :: Row ,
101
108
align_items: AlignItems :: Center ,
102
- ..Default :: default ( )
103
- } => [
104
- (
105
- Text ( format!( "⯆ {name}" ) ) ,
106
- TextFont :: from_font_size( 14.0 ) ,
107
- TextColor ( Color :: WHITE ) ,
108
- ) ;
109
- ] ;
109
+ } [
110
+ TextFont :: from_font_size( 14.0 )
111
+ Text ( { format!( "{name}" ) } )
112
+ TextColor ( Color :: WHITE )
113
+ ] ,
110
114
// Component fields
111
- @ { match reflect {
112
- Some ( reflect) => component( type_info, reflect) ,
113
- None => template ! {
115
+ ( { match reflect {
116
+ Some ( reflect) => component( type_info, reflect) . boxed_scene ( ) ,
117
+ None => bsn ! {
114
118
Node {
115
119
flex_direction: FlexDirection :: Row ,
116
- ..Default :: default ( )
117
- } => [
118
- (
119
- Text ( "<unavailable>" . into( ) ) ,
120
- TextFont :: from_font_size( 10.0 ) ,
121
- TextColor ( Color :: srgb( 1.0 , 0.0 , 0.0 ) ) ,
122
- ) ;
123
- ] ;
124
- } ,
125
- } } ;
126
- ] ;
120
+ } [
121
+ Text ( "<unavailable>" )
122
+ TextFont :: from_font_size( 10.0 )
123
+ TextColor ( Color :: srgb( 1.0 , 0.0 , 0.0 ) )
124
+ ]
125
+ } . boxed_scene( ) ,
126
+ } } )
127
+ ]
127
128
}
128
129
} )
129
- . collect ( )
130
+ . collect :: < Vec < _ > > ( )
130
131
}
131
132
132
- fn component ( type_info : Option < & TypeInfo > , reflect : & dyn Reflect ) -> Template {
133
+ fn component ( type_info : Option < & TypeInfo > , reflect : & dyn Reflect ) -> impl Scene {
133
134
match type_info {
134
- Some ( TypeInfo :: Struct ( struct_info ) ) => reflected_struct ( struct_info , reflect) ,
135
- Some ( TypeInfo :: TupleStruct ( tuple_struct_info ) ) => reflected_tuple_struct ( tuple_struct_info ) ,
136
- Some ( TypeInfo :: Enum ( enum_info ) ) => reflected_enum ( enum_info ) ,
137
- _ => template ! { } ,
135
+ Some ( TypeInfo :: Struct ( info ) ) => reflected_struct ( info , reflect) . boxed_scene ( ) ,
136
+ Some ( TypeInfo :: TupleStruct ( info ) ) => reflected_tuple_struct ( info ) . boxed_scene ( ) ,
137
+ Some ( TypeInfo :: Enum ( info ) ) => reflected_enum ( info ) . boxed_scene ( ) ,
138
+ _ => bsn ! { } . boxed_scene ( ) ,
138
139
}
139
140
}
140
- fn reflected_struct ( struct_info : & StructInfo , reflect : & dyn Reflect ) -> Template {
141
+ fn reflected_struct ( struct_info : & StructInfo , reflect : & dyn Reflect ) -> impl Scene {
141
142
let fields = struct_info
142
143
. iter ( )
143
144
. enumerate ( )
144
- . flat_map ( |( i, field) | {
145
- let value = reflect
145
+ . map ( |( i, field) | {
146
+ let valuee = reflect
146
147
. reflect_ref ( )
147
148
. as_struct ( )
148
149
. map ( |s| s. field_at ( i) )
149
150
. map ( |v| format ! ( "{v:?}" ) )
150
151
. unwrap_or ( "<unavailable>" . to_string ( ) ) ;
151
152
152
- template ! {
153
+ let field_name = field. name ( ) ;
154
+ bsn ! {
153
155
Node {
154
156
flex_direction: FlexDirection :: Row ,
155
157
margin: UiRect :: vertical( Val :: Px ( 2.0 ) ) ,
156
- ..Default :: default ( )
157
- } => [
158
+ } [
158
159
(
159
- Text ( field . name ( ) . to_string ( ) ) ,
160
- TextFont :: from_font_size( 12.0 ) ,
161
- TextColor ( Color :: srgb( 0.8 , 0.8 , 0.8 ) ) ,
162
- ) ;
160
+ Text ( field_name )
161
+ TextFont :: from_font_size( 12.0 )
162
+ TextColor ( Color :: srgb( 0.8 , 0.8 , 0.8 ) )
163
+ ) ,
163
164
(
164
165
// Value (use reflection to get value as string)
165
- Text ( value ) ,
166
- TextFont :: from_font_size( 10.0 ) ,
167
- TextColor ( Color :: WHITE ) ,
168
- ) ;
169
- ] ;
166
+ Text ( { valuee . clone ( ) } )
167
+ TextFont :: from_font_size( 10.0 )
168
+ TextColor ( Color :: WHITE )
169
+ ) ,
170
+ ]
170
171
}
171
172
} )
172
- . collect :: < Template > ( ) ;
173
+ . collect :: < Vec < _ > > ( ) ;
173
174
174
- template ! {
175
+ bsn ! {
175
176
Node {
176
177
flex_direction: FlexDirection :: Column ,
177
- ..Default :: default ( )
178
- } => [ @{ fields } ; ] ;
178
+ } [ { fields} ]
179
179
}
180
180
}
181
181
182
- fn reflected_tuple_struct ( tuple_struct_info : & TupleStructInfo ) -> Template {
182
+ fn reflected_tuple_struct ( tuple_struct_info : & TupleStructInfo ) -> impl Scene {
183
183
let fields = tuple_struct_info
184
184
. iter ( )
185
- . flat_map ( |_field| {
186
- template ! { (
187
- Text ( "TODO" . into ( ) ) ,
188
- TextFont :: from_font_size( 10.0 ) ,
189
- ) ; }
185
+ . map ( |_field| {
186
+ bsn ! {
187
+ Text ( "TODO" )
188
+ TextFont :: from_font_size( 10.0 )
189
+ }
190
190
} )
191
- . collect :: < Template > ( ) ;
191
+ . collect :: < Vec < _ > > ( ) ;
192
192
193
- template ! {
193
+ bsn ! {
194
194
Node {
195
195
flex_direction: FlexDirection :: Column ,
196
- ..Default :: default ( )
197
- } => [ @{ fields } ; ] ;
196
+ } [ { fields} ]
198
197
}
199
198
}
200
199
201
- fn reflected_enum ( enum_info : & EnumInfo ) -> Template {
200
+ fn reflected_enum ( enum_info : & EnumInfo ) -> impl Scene {
202
201
let variants = enum_info
203
202
. iter ( )
204
- . flat_map ( |variant| {
205
- template ! { (
206
- Text ( variant. name( ) . into( ) ) ,
207
- TextFont :: from_font_size( 10.0 ) ,
208
- ) ; }
203
+ . map ( |variant| {
204
+ let name = variant. name ( ) ;
205
+ bsn ! {
206
+ Text ( name)
207
+ TextFont :: from_font_size( 10.0 )
208
+ }
209
209
} )
210
- . collect :: < Template > ( ) ;
210
+ . collect :: < Vec < _ > > ( ) ;
211
211
212
- template ! {
212
+ bsn ! {
213
213
Node {
214
214
flex_direction: FlexDirection :: Column ,
215
- ..Default :: default ( )
216
- } => [ @{ variants } ; ] ;
215
+ } [ { variants} ]
217
216
}
218
217
}
0 commit comments