1
- use re_chunk_store:: { external:: re_chunk:: Arrow2Array , RowId } ;
2
1
use re_types_core:: {
3
- reflection:: { ArchetypeFieldReflection , ArchetypeReflection } ,
4
- Archetype , ArchetypeName , ArchetypeReflectionMarker , ComponentName ,
2
+ reflection:: ArchetypeFieldReflection , Archetype , ArchetypeReflectionMarker , ComponentName ,
5
3
} ;
6
4
use re_ui:: { list_item, UiExt as _} ;
7
5
use re_viewer_context:: {
8
6
ComponentFallbackProvider , ComponentUiTypes , QueryContext , SpaceViewId , SpaceViewState ,
9
7
ViewerContext ,
10
8
} ;
11
- use re_viewport_blueprint:: entity_path_for_view_property ;
9
+ use re_viewport_blueprint:: ViewProperty ;
12
10
13
11
/// Display the UI for editing all components of a blueprint archetype.
14
12
///
@@ -20,79 +18,49 @@ pub fn view_property_ui<A: Archetype + ArchetypeReflectionMarker>(
20
18
fallback_provider : & dyn ComponentFallbackProvider ,
21
19
view_state : & dyn SpaceViewState ,
22
20
) {
23
- let name = A :: name ( ) ;
24
- if let Some ( reflection) = ctx. reflection . archetypes . get ( & name) {
25
- view_property_ui_impl (
26
- ctx,
27
- ui,
28
- view_id,
29
- name,
30
- reflection,
31
- view_state,
32
- fallback_provider,
33
- ) ;
34
- } else {
35
- // The `ArchetypeReflectionMarker` bound should make this impossible.
36
- re_log:: warn_once!( "Missing reflection data for archetype {name:?}." ) ;
37
- }
21
+ let view_property =
22
+ ViewProperty :: from_archetype :: < A > ( ctx. blueprint_db ( ) , ctx. blueprint_query , view_id) ;
23
+ view_property_ui_impl ( ctx, ui, & view_property, fallback_provider, view_state) ;
38
24
}
39
25
40
26
fn view_property_ui_impl (
41
27
ctx : & ViewerContext < ' _ > ,
42
28
ui : & mut egui:: Ui ,
43
- view_id : SpaceViewId ,
44
- name : ArchetypeName ,
45
- reflection : & ArchetypeReflection ,
46
- view_state : & dyn SpaceViewState ,
29
+ property : & ViewProperty ,
47
30
fallback_provider : & dyn ComponentFallbackProvider ,
31
+ view_state : & dyn SpaceViewState ,
48
32
) {
49
- let blueprint_path = entity_path_for_view_property ( view_id, ctx. blueprint_db ( ) . tree ( ) , name) ;
50
- let query_ctx = QueryContext {
51
- viewer_ctx : ctx,
52
- target_entity_path : & blueprint_path,
53
- archetype_name : Some ( name) ,
54
- query : ctx. blueprint_query ,
55
- view_state,
56
- view_ctx : None ,
33
+ let Some ( reflection) = ctx. reflection . archetypes . get ( & property. archetype_name ) else {
34
+ // The `ArchetypeReflectionMarker` bound should make this impossible.
35
+ re_log:: warn_once!(
36
+ "Missing reflection data for archetype {:?}." ,
37
+ property. archetype_name
38
+ ) ;
39
+ return ;
57
40
} ;
58
41
59
- let component_results = ctx. blueprint_db ( ) . latest_at (
60
- ctx. blueprint_query ,
61
- & blueprint_path,
62
- reflection. fields . iter ( ) . map ( |field| field. component_name ) ,
63
- ) ;
64
-
42
+ let query_ctx = property. query_context ( ctx, view_state) ;
65
43
// If the property archetype only has a single component, don't show an additional hierarchy level!
66
44
if reflection. fields . len ( ) == 1 {
67
45
let field = & reflection. fields [ 0 ] ;
68
46
69
- let component_array = component_results. component_batch_raw ( & field. component_name ) ;
70
47
view_property_component_ui (
71
48
& query_ctx,
72
49
ui,
73
- field . component_name ,
50
+ property ,
74
51
reflection. display_name ,
75
52
field,
76
- & blueprint_path,
77
- component_results. component_row_id ( & field. component_name ) ,
78
- component_array. as_deref ( ) ,
79
53
fallback_provider,
80
54
) ;
81
55
} else {
82
56
let sub_prop_ui = |ui : & mut egui:: Ui | {
83
57
for field in & reflection. fields {
84
- let display_name = & field. display_name ;
85
-
86
- let component_array = component_results. component_batch_raw ( & field. component_name ) ;
87
58
view_property_component_ui (
88
59
& query_ctx,
89
60
ui,
90
- field . component_name ,
91
- display_name,
61
+ property ,
62
+ field . display_name ,
92
63
field,
93
- & blueprint_path,
94
- component_results. component_row_id ( & field. component_name ) ,
95
- component_array. as_deref ( ) ,
96
64
fallback_provider,
97
65
) ;
98
66
}
@@ -102,7 +70,7 @@ fn view_property_ui_impl(
102
70
. interactive ( false )
103
71
. show_hierarchical_with_children (
104
72
ui,
105
- ui. make_persistent_id ( name . full_name ( ) ) ,
73
+ ui. make_persistent_id ( property . archetype_name . full_name ( ) ) ,
106
74
true ,
107
75
list_item:: LabelContent :: new ( reflection. display_name ) ,
108
76
sub_prop_ui,
@@ -111,36 +79,91 @@ fn view_property_ui_impl(
111
79
}
112
80
113
81
/// Draw view property ui for a single component of a view property archetype.
114
- #[ allow( clippy:: too_many_arguments) ]
115
- fn view_property_component_ui (
82
+ ///
83
+ /// Use [`view_property_ui`] whenever possible to show the ui for all components of a view property archetype.
84
+ /// This function is only useful if you want to show custom ui for some of the components.
85
+ pub fn view_property_component_ui (
116
86
ctx : & QueryContext < ' _ > ,
117
87
ui : & mut egui:: Ui ,
118
- component_name : ComponentName ,
119
- root_item_display_name : & str ,
88
+ property : & ViewProperty ,
89
+ display_name : & str ,
120
90
field : & ArchetypeFieldReflection ,
121
- blueprint_path : & re_log_types:: EntityPath ,
122
- row_id : Option < RowId > ,
123
- component_array : Option < & dyn Arrow2Array > ,
124
91
fallback_provider : & dyn ComponentFallbackProvider ,
125
92
) {
126
- let singleline_list_item_content = singleline_list_item_content (
127
- ctx,
128
- root_item_display_name,
129
- blueprint_path,
130
- component_name,
131
- row_id,
132
- component_array,
133
- fallback_provider,
134
- ) ;
93
+ let component_array = property. component_raw ( field. component_name ) ;
94
+ let row_id = property. component_row_id ( field. component_name ) ;
135
95
136
96
let ui_types = ctx
137
97
. viewer_ctx
138
98
. component_ui_registry
139
- . registered_ui_types ( component_name) ;
99
+ . registered_ui_types ( field. component_name ) ;
100
+
101
+ let singleline_ui: & dyn Fn ( & mut egui:: Ui ) = & |ui| {
102
+ ctx. viewer_ctx . component_ui_registry . singleline_edit_ui (
103
+ ctx,
104
+ ui,
105
+ ctx. viewer_ctx . blueprint_db ( ) ,
106
+ ctx. target_entity_path ,
107
+ field. component_name ,
108
+ row_id,
109
+ component_array. as_deref ( ) ,
110
+ fallback_provider,
111
+ ) ;
112
+ } ;
113
+
114
+ let multiline_ui: & dyn Fn ( & mut egui:: Ui ) = & |ui| {
115
+ ctx. viewer_ctx . component_ui_registry . multiline_edit_ui (
116
+ ctx,
117
+ ui,
118
+ ctx. viewer_ctx . blueprint_db ( ) ,
119
+ ctx. target_entity_path ,
120
+ field. component_name ,
121
+ row_id,
122
+ component_array. as_deref ( ) ,
123
+ fallback_provider,
124
+ ) ;
125
+ } ;
126
+ // Do this as a separate step to avoid borrowing issues.
127
+ let multiline_ui_ref: Option < & dyn Fn ( & mut egui:: Ui ) > =
128
+ if ui_types. contains ( ComponentUiTypes :: MultiLineEditor ) {
129
+ Some ( multiline_ui)
130
+ } else {
131
+ None
132
+ } ;
140
133
141
- let list_item_response = if ui_types. contains ( ComponentUiTypes :: MultiLineEditor ) {
134
+ view_property_component_ui_custom (
135
+ ctx,
136
+ ui,
137
+ property,
138
+ display_name,
139
+ field,
140
+ singleline_ui,
141
+ multiline_ui_ref,
142
+ ) ;
143
+ }
144
+
145
+ /// Draw view property ui for a single component of a view property archetype with custom ui for singleline & multiline.
146
+ ///
147
+ /// Use [`view_property_ui`] whenever possible to show the ui for all components of a view property archetype.
148
+ /// This function is only useful if you want to show custom ui for some of the components.
149
+ pub fn view_property_component_ui_custom (
150
+ ctx : & QueryContext < ' _ > ,
151
+ ui : & mut egui:: Ui ,
152
+ property : & ViewProperty ,
153
+ display_name : & str ,
154
+ field : & ArchetypeFieldReflection ,
155
+ singleline_ui : & dyn Fn ( & mut egui:: Ui ) ,
156
+ multiline_ui : Option < & dyn Fn ( & mut egui:: Ui ) > ,
157
+ ) {
158
+ let singleline_list_item_content = list_item:: PropertyContent :: new ( display_name)
159
+ . menu_button ( & re_ui:: icons:: MORE , |ui| {
160
+ menu_more ( ctx. viewer_ctx , ui, property, field. component_name ) ;
161
+ } )
162
+ . value_fn ( move |ui, _| singleline_ui ( ui) ) ;
163
+
164
+ let list_item_response = if let Some ( multiline_ui) = multiline_ui {
142
165
let default_open = false ;
143
- let id = egui:: Id :: new ( ( blueprint_path . hash ( ) , component_name) ) ;
166
+ let id = egui:: Id :: new ( ( ctx . target_entity_path . hash ( ) , field . component_name ) ) ;
144
167
ui. list_item ( )
145
168
. interactive ( false )
146
169
. show_hierarchical_with_children (
@@ -149,16 +172,7 @@ fn view_property_component_ui(
149
172
default_open,
150
173
singleline_list_item_content,
151
174
|ui| {
152
- ctx. viewer_ctx . component_ui_registry . multiline_edit_ui (
153
- ctx,
154
- ui,
155
- ctx. viewer_ctx . blueprint_db ( ) ,
156
- blueprint_path,
157
- component_name,
158
- row_id,
159
- component_array,
160
- fallback_provider,
161
- ) ;
175
+ multiline_ui ( ui) ;
162
176
} ,
163
177
)
164
178
. item_response
@@ -177,14 +191,13 @@ fn view_property_component_ui(
177
191
fn menu_more (
178
192
ctx : & ViewerContext < ' _ > ,
179
193
ui : & mut egui:: Ui ,
180
- blueprint_path : & re_log_types :: EntityPath ,
194
+ property : & ViewProperty ,
181
195
component_name : ComponentName ,
182
- component_array : Option < & dyn Arrow2Array > ,
183
196
) {
197
+ let component_array = property. component_raw ( component_name) ;
198
+
184
199
let property_differs_from_default = component_array
185
- != ctx
186
- . raw_latest_at_in_default_blueprint ( blueprint_path, component_name)
187
- . as_deref ( ) ;
200
+ != ctx. raw_latest_at_in_default_blueprint ( & property. blueprint_store_path , component_name) ;
188
201
189
202
let response = ui
190
203
. add_enabled (
@@ -199,7 +212,7 @@ If no default blueprint was set or it didn't set any value for this field, this
199
212
"The property is already set to the same value it has in the default blueprint" ,
200
213
) ;
201
214
if response. clicked ( ) {
202
- ctx. reset_blueprint_component_by_name ( blueprint_path , component_name) ;
215
+ ctx. reset_blueprint_component_by_name ( & property . blueprint_store_path , component_name) ;
203
216
ui. close_menu ( ) ;
204
217
}
205
218
@@ -214,43 +227,10 @@ This has the same effect as not setting the value in the blueprint at all."
214
227
)
215
228
. on_disabled_hover_text ( "The property is already unset." ) ;
216
229
if response. clicked ( ) {
217
- ctx. clear_blueprint_component_by_name ( blueprint_path , component_name) ;
230
+ ctx. clear_blueprint_component_by_name ( & property . blueprint_store_path , component_name) ;
218
231
ui. close_menu ( ) ;
219
232
}
220
233
221
234
// TODO(andreas): The next logical thing here is now to save it to the default blueprint!
222
235
// This should be fairly straight forward except that we need to make sure that a default blueprint exists in the first place.
223
236
}
224
-
225
- fn singleline_list_item_content < ' a > (
226
- ctx : & ' a QueryContext < ' _ > ,
227
- display_name : & str ,
228
- blueprint_path : & ' a re_log_types:: EntityPath ,
229
- component_name : ComponentName ,
230
- row_id : Option < RowId > ,
231
- component_array : Option < & ' a dyn Arrow2Array > ,
232
- fallback_provider : & ' a dyn ComponentFallbackProvider ,
233
- ) -> list_item:: PropertyContent < ' a > {
234
- list_item:: PropertyContent :: new ( display_name)
235
- . menu_button ( & re_ui:: icons:: MORE , move |ui| {
236
- menu_more (
237
- ctx. viewer_ctx ,
238
- ui,
239
- blueprint_path,
240
- component_name,
241
- component_array,
242
- ) ;
243
- } )
244
- . value_fn ( move |ui, _| {
245
- ctx. viewer_ctx . component_ui_registry . singleline_edit_ui (
246
- ctx,
247
- ui,
248
- ctx. viewer_ctx . blueprint_db ( ) ,
249
- blueprint_path,
250
- component_name,
251
- row_id,
252
- component_array,
253
- fallback_provider,
254
- ) ;
255
- } )
256
- }
0 commit comments