use std::sync::Arc;
use eframe::egui;
use crate::app::AppState;
use crate::app_impl::constants::SPACE;
use crate::grid_options::MarkerVisibility;
use crate::movable::Draggable;
use maps_io_ros::{ColorMap, MapPose, Meta, load_image_from_bytes, value_interpretation};
use maps_rendering::ImagePyramid;
use maps_rendering::image::to_egui_image;
#[cfg(target_arch = "wasm32")]
pub(crate) fn demo_button(
ui: &mut egui::Ui,
button_handle: &mut Option<egui::TextureHandle>,
texture_name: &str,
image_bytes: &[u8],
alt_text: &str,
) -> bool {
if button_handle.is_none() {
*button_handle = Some(ui.ctx().load_texture(
texture_name,
to_egui_image(&load_image_from_bytes(image_bytes).expect("broken demo")),
Default::default(),
));
}
ui.add(
egui::Button::image(
egui::Image::new(button_handle.as_ref().expect("missing demo image"))
.max_height(200.)
.max_width(300.)
.alt_text(alt_text),
)
.corner_radius(5.),
)
.on_hover_text(alt_text)
.clicked()
}
#[cfg(target_arch = "wasm32")]
fn load_cartographer_demo(app_state: &mut AppState) {
let tints = [
egui::Color32::from_rgba_premultiplied(123, 45, 0, 128),
egui::Color32::from_rgba_premultiplied(32, 67, 32, 74),
egui::Color32::from_rgba_premultiplied(97, 52, 76, 97),
];
macro_rules! load_map {
($index:literal) => {{
let name = format!("map_{}.yaml", $index);
let img = Arc::new(ImagePyramid::new(
load_image_from_bytes(include_bytes!(concat!(
"../../data/google_cartographer_example/jpeg/map_",
stringify!($index),
".jpg"
)))
.expect("broken demo"),
));
let meta = Meta::load_from_bytes(
include_bytes!(concat!(
"../../data/google_cartographer_example/map_",
stringify!($index),
".yaml"
)),
&name,
)
.expect("broken demo");
app_state.add_map(&name, meta, &img);
let map = app_state
.data
.maps
.get_mut(&name)
.expect("missing demo map");
map.tint = Some(tints[$index]);
map.color_to_alpha = Some(egui::Color32::from_gray(128));
map.pose = MapPose::from_bytes(include_bytes!(concat!(
"../../data/google_cartographer_example/pose_",
stringify!($index),
".yaml"
)))
.expect("broken demo");
}};
}
load_map!(0);
load_map!(1);
load_map!(2);
app_state.options.tint_settings.active_tint_selection = Some("map_2.yaml".to_owned());
app_state.options.grid.scale = 5.5;
app_state.options.grid.drag(egui::vec2(-75., 30.));
app_state.options.grid.line_spacing_meters = 25.;
app_state.options.grid.marker_visibility = MarkerVisibility::All;
app_state.options.grid.marker_length_meters = 5.;
app_state.options.grid.marker_width_meters = 0.75;
app_state.options.canvas_settings.theme_preference = egui::ThemePreference::Dark;
app_state.options.collapsed.app_settings = true;
app_state.options.collapsed.canvas_settings = true;
app_state.options.collapsed.tool_settings = true;
}
#[cfg(target_arch = "wasm32")]
impl AppState {
pub(crate) fn demo_buttons(&mut self, ui: &mut egui::Ui) {
egui::ScrollArea::vertical().show(ui, |ui| {
self.load_demo_nav2_button(ui);
ui.add_space(2. * SPACE);
self.load_demo_maps_button(ui);
});
}
pub(crate) fn load_demo_maps_button(&mut self, ui: &mut egui::Ui) {
if demo_button(
ui,
&mut self.data.demo_button_image_handle,
"_demo_button",
include_bytes!("../../data/doc/demo_scaled.png"),
"Demo showcasing very large map images, with maps of the Cartographer Deutsches Museum dataset.",
) {
self.delete(&self.data.maps.keys().cloned().collect());
load_cartographer_demo(self);
}
}
pub(crate) fn load_demo_nav2_button(&mut self, ui: &mut egui::Ui) {
if demo_button(
ui,
&mut self.data.nav2_demo_button_image_handle,
"_nav2_demo_button",
include_bytes!("../../data/doc/demo_nav2_scaled.png"),
"Demo showcasing a typical mobile robot warehouse scenario, with maps from the Nav2 demo.",
) {
self.delete(&self.data.maps.keys().cloned().collect());
load_nav2_demo(self);
}
}
}
#[cfg(target_arch = "wasm32")]
struct Nav2MapConfig<'a> {
name: &'a str,
image_bytes: &'a [u8],
yaml_bytes: &'a [u8],
pose_bytes: &'a [u8],
value_mode: Option<value_interpretation::Mode>,
colormap: Option<ColorMap>,
color_to_alpha: Option<egui::Color32>,
tint: Option<egui::Color32>,
}
#[cfg(target_arch = "wasm32")]
fn load_nav2_map(app_state: &mut AppState, config: &Nav2MapConfig) {
let name = config.name.to_string();
let img = Arc::new(ImagePyramid::new(
load_image_from_bytes(config.image_bytes).expect("broken nav2 demo"),
));
let mut meta = Meta::load_from_bytes(config.yaml_bytes, &name).expect("broken nav2 demo");
if let Some(mode) = config.value_mode {
meta.value_interpretation.mode = mode;
meta.value_interpretation.explicit_mode = true;
}
if let Some(cmap) = config.colormap {
meta.value_interpretation.colormap = cmap;
}
app_state.add_map(&name, meta, &img);
let map = app_state
.data
.maps
.get_mut(&name)
.expect("missing nav2 demo map");
map.tint = config.tint;
if let Some(alpha_color) = config.color_to_alpha {
map.color_to_alpha = Some(alpha_color);
}
map.pose = MapPose::from_bytes(config.pose_bytes).expect("broken nav2 demo");
map.use_value_interpretation = config.value_mode.is_some();
}
#[cfg(target_arch = "wasm32")]
fn load_nav2_demo(app_state: &mut AppState) {
load_nav2_map(
app_state,
&Nav2MapConfig {
name: "warehouse.yaml",
image_bytes: include_bytes!("../../data/nav2_example/warehouse.png"),
yaml_bytes: include_bytes!("../../data/nav2_example/warehouse.yaml"),
pose_bytes: include_bytes!("../../data/nav2_example/map_pose_warehouse.yaml"),
value_mode: Some(value_interpretation::Mode::Trinary),
colormap: Some(ColorMap::RvizMap),
color_to_alpha: None,
tint: None,
},
);
load_nav2_map(
app_state,
&Nav2MapConfig {
name: "warehouse_speed.yaml",
image_bytes: include_bytes!("../../data/nav2_example/warehouse_speed.png"),
yaml_bytes: include_bytes!("../../data/nav2_example/warehouse_speed.yaml"),
pose_bytes: include_bytes!("../../data/nav2_example/map_pose_warehouse.yaml"),
value_mode: Some(value_interpretation::Mode::Scale),
colormap: Some(ColorMap::RvizMap),
color_to_alpha: None,
tint: Some(egui::Color32::from_rgba_premultiplied(140, 140, 140, 140)),
},
);
load_nav2_map(
app_state,
&Nav2MapConfig {
name: "warehouse_keepout.yaml",
image_bytes: include_bytes!("../../data/nav2_example/warehouse_keepout.png"),
yaml_bytes: include_bytes!("../../data/nav2_example/warehouse_keepout.yaml"),
pose_bytes: include_bytes!("../../data/nav2_example/map_pose_warehouse.yaml"),
value_mode: Some(value_interpretation::Mode::Trinary),
colormap: Some(ColorMap::RvizCostmap),
color_to_alpha: None,
tint: Some(egui::Color32::from_rgba_premultiplied(140, 140, 140, 140)),
},
);
load_nav2_map(
app_state,
&Nav2MapConfig {
name: "depot_speed.yaml",
image_bytes: include_bytes!("../../data/nav2_example/depot_speed.png"),
yaml_bytes: include_bytes!("../../data/nav2_example/depot_speed.yaml"),
pose_bytes: include_bytes!("../../data/nav2_example/map_pose_depot.yaml"),
value_mode: Some(value_interpretation::Mode::Scale),
colormap: Some(ColorMap::CoolCostmap),
color_to_alpha: None,
tint: None,
},
);
load_nav2_map(
app_state,
&Nav2MapConfig {
name: "depot_keepout.yaml",
image_bytes: include_bytes!("../../data/nav2_example/depot_keepout.png"),
yaml_bytes: include_bytes!("../../data/nav2_example/depot_keepout.yaml"),
pose_bytes: include_bytes!("../../data/nav2_example/map_pose_depot.yaml"),
value_mode: Some(value_interpretation::Mode::Trinary),
colormap: Some(ColorMap::RvizCostmap),
color_to_alpha: None,
tint: Some(egui::Color32::from_rgba_premultiplied(140, 140, 140, 140)),
},
);
load_nav2_map(
app_state,
&Nav2MapConfig {
name: "depot.yaml",
image_bytes: include_bytes!("../../data/nav2_example/depot.png"),
yaml_bytes: include_bytes!("../../data/nav2_example/depot.yaml"),
pose_bytes: include_bytes!("../../data/nav2_example/map_pose_depot.yaml"),
value_mode: None,
colormap: None,
color_to_alpha: Some(egui::Color32::from_rgba_premultiplied(254, 254, 254, 255)),
tint: None,
},
);
app_state.options.grid.scale = 10.0;
app_state.options.grid.drag(egui::vec2(-30., 30.));
app_state.options.grid.line_spacing_meters = 10.;
app_state.options.grid.marker_visibility = MarkerVisibility::All;
app_state.options.grid.marker_length_meters = 2.;
app_state.options.grid.marker_width_meters = 0.3;
app_state.options.collapsed.app_settings = true;
app_state.options.collapsed.canvas_settings = true;
app_state.options.collapsed.tool_settings = true;
}