Skip to content

Commit

Permalink
introduce multiline edits and use it to implement 2d bounds editing
Browse files Browse the repository at this point in the history
  • Loading branch information
Wumpf committed Jun 4, 2024
1 parent be35f0b commit 384fc6b
Show file tree
Hide file tree
Showing 14 changed files with 599 additions and 211 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5271,6 +5271,7 @@ dependencies = [
"anyhow",
"arboard",
"bit-vec",
"bitflags 2.5.0",
"bytemuck",
"egui",
"egui-wgpu",
Expand Down
2 changes: 1 addition & 1 deletion crates/re_data_ui/src/component_ui_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn create_component_ui_registry() -> ComponentUiRegistry {

/// Registers how to show a given component in the ui.
pub fn add_to_registry<C: EntityDataUi + re_types::Component>(registry: &mut ComponentUiRegistry) {
registry.add(
registry.add_display_ui(
C::name(),
Box::new(
|ctx, ui, ui_layout, query, db, entity_path, component, instance| {
Expand Down
29 changes: 17 additions & 12 deletions crates/re_edit_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,25 @@ fn edit_color_ui(_ctx: &ViewerContext<'_>, ui: &mut egui::Ui, value: &mut Color)
/// ⚠️ This is supposed to be the only export of this crate.
/// This crate is meant to be a leaf crate in the viewer ecosystem and should only be used by the `re_viewer` crate itself.
pub fn register_editors(registry: &mut re_viewer_context::ComponentUiRegistry) {
registry.add_editor(edit_color_ui);
registry.add_editor(marker_shape::edit_marker_shape_ui);
registry.add_editor(visual_bounds_2d::edit_visual_bounds_2d);
registry.add_singleline_editor_ui(edit_color_ui);
registry.add_singleline_editor_ui(marker_shape::edit_marker_shape_ui);

registry.add_editor::<Visible>(datatype_editors::edit_bool);
registry.add_singleline_editor_ui::<Visible>(datatype_editors::edit_bool);

registry.add_editor::<Text>(datatype_editors::edit_singleline_string);
registry.add_editor::<Name>(datatype_editors::edit_singleline_string);
registry.add_singleline_editor_ui::<Text>(datatype_editors::edit_singleline_string);
registry.add_singleline_editor_ui::<Name>(datatype_editors::edit_singleline_string);

registry.add_editor::<Radius>(datatype_editors::edit_f32_zero_to_inf);
registry.add_editor::<MarkerSize>(datatype_editors::edit_f32_zero_to_inf);
registry.add_editor::<StrokeWidth>(datatype_editors::edit_f32_zero_to_inf);
registry.add_singleline_editor_ui::<Radius>(datatype_editors::edit_f32_zero_to_inf);
registry.add_singleline_editor_ui::<MarkerSize>(datatype_editors::edit_f32_zero_to_inf);
registry.add_singleline_editor_ui::<StrokeWidth>(datatype_editors::edit_f32_zero_to_inf);

registry.add_editor(|_ctx, ui, value| edit_enum(ui, "corner2d", value, &Corner2D::ALL));
registry
.add_editor(|_ctx, ui, value| edit_enum(ui, "backgroundkind", value, &BackgroundKind::ALL));
registry.add_singleline_editor_ui(|_ctx, ui, value| {
edit_enum(ui, "corner2d", value, &Corner2D::ALL)
});
registry.add_singleline_editor_ui(|_ctx, ui, value| {
edit_enum(ui, "backgroundkind", value, &BackgroundKind::ALL)
});

registry.add_multiline_editor_ui(visual_bounds_2d::multiline_edit_visual_bounds_2d);
registry.add_singleline_editor_ui(visual_bounds_2d::singleline_edit_visual_bounds_2d);
}
164 changes: 125 additions & 39 deletions crates/re_edit_ui/src/visual_bounds_2d.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,137 @@
use egui::NumExt as _;
use re_types::blueprint::components::VisualBounds2D;
use re_types::{blueprint::components::VisualBounds2D, datatypes::Range2D};
use re_viewer_context::ViewerContext;

pub fn edit_visual_bounds_2d(
_ctx: &ViewerContext<'_>,
pub fn multiline_edit_visual_bounds_2d(
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
value: &mut VisualBounds2D,
) -> egui::Response {
let speed_func = |start: f64, end: f64| ((end - start).abs() * 0.01).at_least(0.001);

ui.vertical(|ui| {
ui.horizontal(|ui| {
let [x_range_start, x_range_end] = &mut value.x_range.0;
let speed = speed_func(*x_range_start, *x_range_end);

ui.label("x");
ui.add(
egui::DragValue::new(x_range_start)
.clamp_range(f64::NEG_INFINITY..=*x_range_end)
.max_decimals(2)
.speed(speed),
) | ui.add(
egui::DragValue::new(x_range_end)
.clamp_range(*x_range_start..=f64::INFINITY)
.max_decimals(2)
.speed(speed),
)
})
.inner
| ui.horizontal(|ui| {
let mut any_edit = false;

let response_x = re_ui::list_item::ListItem::new(ctx.re_ui)
.interactive(false)
.show_hierarchical(
ui,
re_ui::list_item::PropertyContent::new("x").value_fn(|_, ui, _| {
let [x_range_start, x_range_end] = &mut value.x_range.0;
let speed = speed_func(*x_range_start, *x_range_end);

let response = ui
.horizontal_centered(|ui| {
let response_min = ui.add(
egui::DragValue::new(x_range_start)
.clamp_range(f64::NEG_INFINITY..=*x_range_end)
.max_decimals(2)
.speed(speed),
);

ui.label("-");

let response_max = ui.add(
egui::DragValue::new(x_range_end)
.clamp_range(*x_range_start..=f64::INFINITY)
.max_decimals(2)
.speed(speed),
);

response_min | response_max
})
.inner;

if response.changed() {
any_edit = true;
}
}),
);

let response_y = re_ui::list_item::ListItem::new(ctx.re_ui)
.interactive(false)
.show_hierarchical(
ui,
re_ui::list_item::PropertyContent::new("y").value_fn(|_, ui, _| {
let [y_range_start, y_range_end] = &mut value.y_range.0;
let speed = speed_func(*y_range_start, *y_range_end);

ui.label("y");
ui.add(
egui::DragValue::new(y_range_start)
.clamp_range(f64::NEG_INFINITY..=*y_range_end)
.max_decimals(2)
.speed(speed),
) | ui.add(
egui::DragValue::new(y_range_end)
.clamp_range(*y_range_start..=f64::INFINITY)
.max_decimals(2)
.speed(speed),
)
})
.inner
})
.inner
let response = ui
.horizontal_centered(|ui| {
let response_min = ui.add(
egui::DragValue::new(y_range_start)
.clamp_range(f64::NEG_INFINITY..=*y_range_end)
.max_decimals(2)
.speed(speed),
);

ui.label("-");

let response_max = ui.add(
egui::DragValue::new(y_range_end)
.clamp_range(*y_range_start..=f64::INFINITY)
.max_decimals(2)
.speed(speed),
);

response_min | response_max
})
.inner;

if response.changed() {
any_edit = true;
}
}),
);

let mut response = response_x | response_y;
if any_edit {
response.mark_changed();
}
response
}

pub fn singleline_edit_visual_bounds_2d(
_ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
value: &mut VisualBounds2D,
) -> egui::Response {
let width = value.x_range.0[1] - value.x_range.0[0];
let height = value.y_range.0[1] - value.y_range.0[0];

let mut width_edit = width;
let mut height_edit = height;

let speed_func = |v: f64| (v.abs() * 0.01).at_least(0.001);

let response_width = ui.add(
egui::DragValue::new(&mut width_edit)
.clamp_range(f64::NEG_INFINITY..=f64::INFINITY)
.max_decimals(1)
.speed(speed_func(width)),
);
ui.label("×");
let response_height = ui.add(
egui::DragValue::new(&mut height_edit)
.clamp_range(f64::NEG_INFINITY..=f64::INFINITY)
.max_decimals(1)
.speed(speed_func(height)),
);

let d_width = width_edit - width;
let d_height = height_edit - height;
*value = Range2D {
x_range: [
value.x_range.0[0] - d_width * 0.5,
value.x_range.0[1] + d_width * 0.5,
]
.into(),
y_range: [
value.y_range.0[0] - d_height * 0.5,
value.y_range.0[1] + d_height * 0.5,
]
.into(),
}
.into();

response_height | response_width
}
8 changes: 8 additions & 0 deletions crates/re_query/src/latest_at/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ impl LatestAtComponentResults {
}
}

/// Returns true if the component is missing, an empty array or still pending.
pub fn is_empty(&self, resolver: &PromiseResolver) -> bool {
match self.resolved(resolver) {
PromiseResult::Ready(cell) => cell.is_empty(),
PromiseResult::Error(_) | PromiseResult::Pending => true,
}
}

/// Returns the component data of the single instance.
///
/// This assumes that the row we get from the store contains at most one instance for this
Expand Down
5 changes: 0 additions & 5 deletions crates/re_query/src/latest_at/results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ impl LatestAtResults {
self.components.contains_key(&component_name.into())
}

pub fn contains_non_empty(&self, component_name: impl Into<ComponentName>) -> bool {
self.get(component_name)
.map_or(false, |result| result.num_instances() != 0)
}

/// Returns the [`LatestAtComponentResults`] for the specified [`Component`].
#[inline]
pub fn get(
Expand Down
17 changes: 10 additions & 7 deletions crates/re_selection_panel/src/override_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use re_entity_db::{EntityDb, InstancePath};
use re_log_types::{DataCell, DataRow, RowId, StoreKind};
use re_types_core::{components::VisualizerOverrides, ComponentName};
use re_viewer_context::{
DataResult, OverridePath, QueryContext, SpaceViewClassExt as _, SystemCommand,
SystemCommandSender as _, UiLayout, ViewSystemIdentifier, ViewerContext,
ComponentUiTypes, DataResult, OverridePath, QueryContext, SpaceViewClassExt as _,
SystemCommand, SystemCommandSender as _, ViewSystemIdentifier, ViewerContext,
};
use re_viewport_blueprint::SpaceViewBlueprint;

Expand Down Expand Up @@ -133,18 +133,16 @@ pub fn override_ui(
.cloned(); /* arc */

if let Some(results) = component_data {
ctx.component_ui_registry.edit_ui(
ctx.component_ui_registry.singleline_edit_ui(
&QueryContext {
viewer_ctx: ctx,
target_entity_path: entity_path_overridden,
target_entity_path: &instance_path.entity_path,
archetype_name: None,
query: &query,
view_state,
},
ui,
UiLayout::List,
origin_db,
&instance_path.entity_path,
entity_path_overridden,
*component_name,
&results,
Expand Down Expand Up @@ -227,7 +225,12 @@ pub fn add_new_override(
};

// If there is no registered editor, don't let the user create an override
if !ctx.component_ui_registry.has_registered_editor(component) {
// TODO(andreas): Can only handle single line editors right now.
if !ctx
.component_ui_registry
.registered_ui_types(*component)
.contains(ComponentUiTypes::SingleLineEditor)
{
continue;
}

Expand Down
10 changes: 6 additions & 4 deletions crates/re_selection_panel/src/query_range_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use re_space_view_spatial::{SpatialSpaceView2D, SpatialSpaceView3D};
use re_space_view_time_series::TimeSeriesSpaceView;
use re_types::{
datatypes::{TimeInt, TimeRange, TimeRangeBoundary},
SpaceViewClassIdentifier,
Archetype, SpaceViewClassIdentifier,
};
use re_ui::{markdown_ui, ReUi};
use re_viewer_context::{QueryRange, SpaceViewClass, ViewerContext};
Expand Down Expand Up @@ -43,9 +43,11 @@ pub fn query_range_ui_space_view(
return;
}

let property_path = entity_path_for_view_property::<
re_types::blueprint::archetypes::VisibleTimeRanges,
>(space_view.id, ctx.store_context.blueprint.tree());
let property_path = entity_path_for_view_property(
space_view.id,
ctx.store_context.blueprint.tree(),
re_types::blueprint::archetypes::VisibleTimeRanges::name(),
);

let query_range = space_view.query_range(
ctx.store_context.blueprint,
Expand Down
Loading

0 comments on commit 384fc6b

Please sign in to comment.