use std::iter;
use egui::Color32;
use itertools::{Either, izip};
use re_entity_db::InstancePathHash;
use re_log_types::{EntityPath, Instance};
use re_sdk_types::blueprint::components::VisualizerInstructionId;
use re_view::clamped_or;
use re_viewer_context::ResolvedAnnotationInfos;
#[derive(Clone)]
pub enum UiLabelTarget {
Rect(egui::Rect),
Point2D(egui::Pos2),
Position3D(glam::Vec3),
}
#[derive(Clone, PartialEq, Eq)]
pub enum UiLabelStyle {
Default,
Color(egui::Color32),
Error,
}
impl From<egui::Color32> for UiLabelStyle {
fn from(color: egui::Color32) -> Self {
Self::Color(color)
}
}
#[derive(Clone)]
pub struct UiLabel {
pub text: String,
pub style: UiLabelStyle,
pub target: UiLabelTarget,
pub labeled_instance: InstancePathHash,
pub visualizer_instruction: VisualizerInstructionId,
}
pub struct LabeledBatch<'a, P: 'a, I: Iterator<Item = P> + 'a> {
pub entity_path: &'a EntityPath,
pub visualizer_instruction: VisualizerInstructionId,
pub num_instances: usize,
pub overall_position: P,
pub instance_positions: I,
pub labels: &'a [re_sdk_types::ArrowString],
pub colors: &'a [egui::Color32],
pub show_labels: re_sdk_types::components::ShowLabels,
pub annotation_infos: &'a ResolvedAnnotationInfos,
}
pub fn process_labels_3d<'a>(
batch: LabeledBatch<'a, glam::Vec3, impl Iterator<Item = glam::Vec3> + 'a>,
world_from_obj: glam::Affine3A,
) -> impl Iterator<Item = UiLabel> + 'a {
process_labels(batch, move |position| {
UiLabelTarget::Position3D(world_from_obj.transform_point3(position))
})
}
pub fn process_labels_2d<'a>(
batch: LabeledBatch<'a, glam::Vec2, impl Iterator<Item = glam::Vec2> + 'a>,
world_from_obj: glam::Affine3A,
) -> impl Iterator<Item = UiLabel> + 'a {
process_labels(batch, move |position| {
let point = world_from_obj.transform_point3(position.extend(0.0));
UiLabelTarget::Point2D(egui::pos2(point.x, point.y))
})
}
pub fn process_labels<'a, P: 'a>(
batch: LabeledBatch<'a, P, impl Iterator<Item = P> + 'a>,
target_from_position: impl Fn(P) -> UiLabelTarget + 'a,
) -> impl Iterator<Item = UiLabel> + 'a {
let LabeledBatch {
entity_path,
visualizer_instruction,
num_instances,
overall_position,
instance_positions,
labels,
colors,
show_labels,
annotation_infos,
} = batch;
let show_labels = bool::from(show_labels.0);
if !show_labels {
return Either::Left(iter::empty());
}
let label_positions = if labels.len() == 1 && num_instances > 1 {
Either::Left(std::iter::once(overall_position))
} else {
Either::Right(instance_positions)
};
let labels = izip!(
annotation_infos.iter(),
labels.iter().map(Some).chain(std::iter::repeat(None))
)
.map(|(annotation_info, label)| annotation_info.label(label.map(|l| l.as_str())));
let colors = clamped_or(colors, &Color32::PLACEHOLDER);
Either::Right(
itertools::izip!(label_positions, labels, colors)
.enumerate()
.filter_map(move |(i, (position, label, color))| {
let label = label?;
(!label.is_empty()).then(|| UiLabel {
text: label,
style: if *color == Color32::PLACEHOLDER {
UiLabelStyle::Default
} else {
UiLabelStyle::Color(*color)
},
target: target_from_position(position),
labeled_instance: InstancePathHash::instance(
entity_path,
Instance::from(i as u64),
),
visualizer_instruction,
})
}),
)
}