From 2b527c0950be20822e38be6c04a01ec8eff63c4e Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Sat, 1 Jul 2023 02:35:01 +0200 Subject: [PATCH] Prevent save/load cycle from editing blueprint due to auto-values --- .../re_data_store/src/editable_auto_value.rs | 10 +++++ crates/re_data_store/src/entity_properties.rs | 33 ++++++++++++++++ crates/re_space_view/src/data_blueprint.rs | 38 +++++++++++++++++-- 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/crates/re_data_store/src/editable_auto_value.rs b/crates/re_data_store/src/editable_auto_value.rs index 717c373c8eb3f..db3bb94aa5e5f 100644 --- a/crates/re_data_store/src/editable_auto_value.rs +++ b/crates/re_data_store/src/editable_auto_value.rs @@ -49,4 +49,14 @@ where self } } + + /// Determine whether this `EditableAutoValue` has user-edits relative to another `EditableAutoValue` + /// This is similar in concept to `PartialEq`, but more forgiving of Auto taking on different values. + pub fn unedited(&self, other: &Self) -> bool { + match (self, other) { + (EditableAutoValue::UserEdited(s), EditableAutoValue::UserEdited(o)) => s == o, + (EditableAutoValue::Auto(_), EditableAutoValue::Auto(_)) => true, + _ => false, + } + } } diff --git a/crates/re_data_store/src/entity_properties.rs b/crates/re_data_store/src/entity_properties.rs index e15169bb4c6a8..589199026e0b7 100644 --- a/crates/re_data_store/src/entity_properties.rs +++ b/crates/re_data_store/src/entity_properties.rs @@ -34,6 +34,15 @@ impl EntityPropertyMap { pub fn iter(&self) -> impl Iterator { self.props.iter() } + + /// Determine whether this `EntityPropertyMap` has user-edits relative to another `EntityPropertyMap` + /// This is similar in concept to `PartialEq`, but more forgiving of Auto taking on different values. + pub fn unedited(&self, other: &Self) -> bool { + self.props + .iter() + .zip(other.props.iter()) + .all(|(x, y)| x.0 == y.0 && x.1.unedited(y.1)) + } } // ---------------------------------------------------------------------------- @@ -116,6 +125,30 @@ impl EntityProperties { .clone(), } } + + /// Determine whether this `EntityProperty` has user-edits relative to another `EntityProperty` + /// This is similar in concept to `PartialEq`, but more forgiving of Auto taking on different values. + pub fn unedited(&self, other: &Self) -> bool { + let Self { + visible, + visible_history, + interactive, + color_mapper, + pinhole_image_plane_distance, + backproject_depth, + depth_from_world_scale, + backproject_radius_scale, + } = self; + + visible == &other.visible + && visible_history == &other.visible_history + && interactive == &other.interactive + && color_mapper.unedited(&other.color_mapper) + && pinhole_image_plane_distance.unedited(&other.pinhole_image_plane_distance) + && backproject_depth.unedited(&other.backproject_depth) + && depth_from_world_scale.unedited(&other.depth_from_world_scale) + && backproject_radius_scale.unedited(&other.backproject_radius_scale) + } } // ---------------------------------------------------------------------------- diff --git a/crates/re_space_view/src/data_blueprint.rs b/crates/re_space_view/src/data_blueprint.rs index 76b518628b5dc..be16eb60833fc 100644 --- a/crates/re_space_view/src/data_blueprint.rs +++ b/crates/re_space_view/src/data_blueprint.rs @@ -7,7 +7,7 @@ use slotmap::SlotMap; use smallvec::{smallvec, SmallVec}; /// A grouping of several data-blueprints. -#[derive(Clone, Default, PartialEq, serde::Deserialize, serde::Serialize)] +#[derive(Clone, Default, serde::Deserialize, serde::Serialize)] pub struct DataBlueprintGroup { pub display_name: String, @@ -31,9 +31,29 @@ pub struct DataBlueprintGroup { pub entities: BTreeSet, } +// Manually implement `PartialEq` since properties_projected is serde skip +impl PartialEq for DataBlueprintGroup { + fn eq(&self, other: &Self) -> bool { + let Self { + display_name, + properties_individual, + properties_projected: _, + parent, + children, + entities, + } = self; + + display_name == &other.display_name + && properties_individual.unedited(&other.properties_individual) + && parent == &other.parent + && children == &other.children + && entities == &other.entities + } +} + /// Data blueprints for all entity paths in a space view. -#[derive(Clone, Default, PartialEq, serde::Deserialize, serde::Serialize)] -struct DataBlueprints { +#[derive(Clone, Default, serde::Deserialize, serde::Serialize)] +pub struct DataBlueprints { /// Individual settings. Mutate this. individual: EntityPropertyMap, @@ -44,6 +64,18 @@ struct DataBlueprints { projected: EntityPropertyMap, } +// Manually implement `PartialEq` since projected is serde skip +impl PartialEq for DataBlueprints { + fn eq(&self, other: &Self) -> bool { + let Self { + individual, + projected: _, + } = self; + + individual.unedited(&other.individual) + } +} + /// Tree of all data blueprint groups for a single space view. #[derive(Clone, serde::Deserialize, serde::Serialize)] pub struct DataBlueprintTree {