#[cfg(feature = "bevy")]
use bevy::{
prelude::{Component, ReflectComponent},
reflect::Reflect,
};
use serde::{Deserialize, Serialize};
use std::{borrow::Cow, collections::BTreeMap};
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "bevy", derive(Component, Reflect))]
#[cfg_attr(feature = "bevy", reflect(Component))]
pub enum Category {
#[default]
General,
Site,
Anchor,
Collision,
Door,
Wall,
Floor,
Inertia,
Joint,
Level,
Lane,
Lift,
Light,
Location,
Measurement,
Fiducial,
FiducialGroup,
TextureGroup,
Model,
ModelDescription,
Camera,
Drawing,
Constraint,
Workcell,
GeoReference,
NavigationGraph,
MutexGroup,
Task,
Visual,
Custom(Cow<'static, str>),
}
impl Category {
pub fn label(&self) -> &str {
match self {
Self::General => "General",
Self::Site => "Site",
Self::Anchor => "Anchor",
Self::Collision => "Collision",
Self::Door => "Door",
Self::Wall => "Wall",
Self::Floor => "Floor",
Self::Inertia => "Inertia",
Self::Joint => "Joint",
Self::Level => "Level",
Self::Lane => "Lane",
Self::Lift => "Lift",
Self::Light => "Light",
Self::Location => "Location",
Self::Measurement => "Measurement",
Self::Fiducial => "Fiducial",
Self::FiducialGroup => "Fiducial Group",
Self::TextureGroup => "Texture Group",
Self::Model => "Model",
Self::ModelDescription => "Model Description",
Self::Camera => "Camera",
Self::Drawing => "Drawing",
Self::Constraint => "Constraint",
Self::Workcell => "Workcell",
Self::GeoReference => "Georeference",
Self::NavigationGraph => "Navigation Graph",
Self::MutexGroup => "Mutex Group",
Self::Task => "Task",
Self::Visual => "Visual",
Self::Custom(label) => label,
}
}
pub fn is_physical(&self) -> bool {
match self {
Self::Door | Self::Wall | Self::Floor | Self::Lift | Self::Model => true,
_ => false,
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(transparent)]
pub struct Categorized<T>(pub(crate) BTreeMap<Category, T>);
impl<T> Categorized<T> {
pub fn new(general: T) -> Self {
Self(BTreeMap::from([(Category::General, general)]))
}
pub fn with_category(mut self, category: Category, value: T) -> Self {
self.0.insert(category, value);
self
}
pub fn for_general(&self) -> &T {
self.0.get(&Category::General).unwrap()
}
pub fn for_category(&self, category: Category) -> &T {
match category {
Category::General => self.0.get(&Category::General).unwrap(),
category => self.0.get(&category).unwrap_or_else(|| self.for_general()),
}
}
}