use std::f32::consts::{FRAC_PI_2, PI};
use bevy::{platform::collections::HashMap, prelude::*};
use petgraph::prelude::*;
use super::rd::{
RdJointLimits, RdMotorModel, RdMotorPosition, RdMotorVelocity, RdName, RdScaler, RdVector,
};
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcSceneRoot;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct BelongsToRcSceneRoot(pub Entity);
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcSceneRootIsProcessed;
#[derive(Debug, Reflect, Component)]
pub struct RcSceneRootReady;
#[derive(Debug, Reflect, Component)]
pub struct RcSceneRootWRobotRootsDetached;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcGroup;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct BelongsToRcGroup(pub Entity);
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcGroupIsProcessed;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcRobotRoot;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcRobotRootIsProcessed;
#[derive(Debug, Clone, Reflect, Component, Default)]
pub struct RcRobotGraph {
#[reflect(ignore)]
graph: StableGraph<RcRobotGraphLink, RcRobotGraphJoint, Directed>,
#[reflect(ignore)]
link_nodes_by_name: HashMap<RdName, NodeIndex>,
#[reflect(ignore)]
joints_edges_by_name: HashMap<RdName, EdgeIndex>,
}
#[derive(Debug, Clone, Reflect, Component)]
pub struct RcRobotGraphLink {
pub link_name: RdName,
pub link_entity: Entity,
}
#[derive(Debug, Clone, Reflect, Component)]
pub struct RcRobotGraphJoint {
pub joint_name: RdName,
pub joint_entity: Entity,
pub from_link: RdName,
pub to_link: RdName,
}
impl RcRobotGraph {
pub fn add_link(&mut self, link: RcRobotGraphLink) -> Option<NodeIndex> {
let node = self.graph.add_node(link.clone());
self.link_nodes_by_name.insert(link.link_name, node);
Some(node)
}
pub fn links(&self) -> impl Iterator<Item = &RcRobotGraphLink> {
self.graph.node_weights()
}
pub fn get_link(&self, name: &RdName) -> Option<&RcRobotGraphLink> {
let node = self.link_nodes_by_name.get(name)?;
let link = self.graph.node_weight(*node);
link
}
pub fn remove_link(
&mut self,
name: &RdName,
) -> Option<(RcRobotGraphLink, Vec<RcRobotGraphJoint>)> {
let node = self.link_nodes_by_name.remove(name)?;
let edges_to_remove = self
.graph
.edges(node)
.map(|edge| edge.id())
.collect::<Vec<_>>();
let mut removed_joints = vec![];
for edge in edges_to_remove {
let Some(joint) = self.graph.remove_edge(edge) else {
continue;
};
self.joints_edges_by_name.remove(&joint.joint_name);
removed_joints.push(joint);
}
let link = self.graph.remove_node(node)?;
Some((link, removed_joints))
}
pub fn add_joint(&mut self, joint: RcRobotGraphJoint) -> Option<EdgeIndex> {
let RcRobotGraphJoint {
joint_name,
from_link,
to_link,
..
} = &joint;
let from_node = self.link_nodes_by_name.get(from_link)?;
let to_node = self.link_nodes_by_name.get(to_link)?;
let edge = self.graph.add_edge(*from_node, *to_node, joint.clone());
self.joints_edges_by_name.insert(joint_name.clone(), edge);
Some(edge)
}
pub fn joints(&self) -> impl Iterator<Item = &RcRobotGraphJoint> {
self.graph.edge_weights()
}
pub fn get_joint(&self, name: &RdName) -> Option<&RcRobotGraphJoint> {
let edge = self.joints_edges_by_name.get(name)?;
let joint = self.graph.edge_weight(*edge);
joint
}
pub fn get_joints_on_link(
&self,
link: &RdName,
) -> Option<impl IntoIterator<Item = &RcRobotGraphJoint>> {
let Some(node) = self.link_nodes_by_name.get(link) else {
warn!("Link not found: {:?}", link);
return None;
};
let edges = self.graph.edges(*node).map(|edge| edge.id());
let joints = edges.filter_map(|edge| self.graph.edge_weight(edge));
Some(joints)
}
pub fn get_joint_connecting(
&self,
from_link: &RdName,
to_link: &RdName,
) -> Option<&RcRobotGraphJoint> {
let from_node = self.link_nodes_by_name.get(from_link)?;
let to_node = self.link_nodes_by_name.get(to_link)?;
let edge = self.graph.find_edge(*from_node, *to_node)?;
let joint = self.graph.edge_weight(edge)?;
Some(joint)
}
pub fn remove_joint(&mut self, name: &RdName) -> Option<RcRobotGraphJoint> {
let edge = self.joints_edges_by_name.remove(name)?;
let joint = self.graph.remove_edge(edge)?;
Some(joint)
}
}
#[derive(Debug, Clone, Reflect, Component)]
pub struct BelongsToRcRobotRoot(pub Entity);
#[derive(Debug, Clone, Reflect, Component, Default)]
#[reflect(Component, Default)]
pub struct RcLink {
pub name: RdName,
pub rigid_body: RcRigidBody,
}
#[derive(Debug, Clone, Reflect, Component)]
pub struct BelongsToRcLink(pub Entity);
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
#[require(RcLink = RcLink::default())]
pub struct RcLinkRoot;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcLinkIsProcessed;
#[derive(Debug, Clone, Reflect, Default)]
pub enum RcRigidBody {
#[default]
Fixed,
Dynamic,
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcCcd;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcDisableSleep;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component, Default)]
#[require(RcColliderConstruction = RcColliderConstruction::default())]
pub struct RcCollider {
pub density: RdScaler,
pub keep_mesh: bool,
}
impl Default for RcCollider {
fn default() -> Self {
Self {
density: 1.0,
keep_mesh: true,
}
}
}
#[derive(Debug, Clone, Reflect, Default, Component)]
#[reflect(Component)]
pub enum RcColliderConstruction {
#[default]
Trimesh,
ConvexHull,
ConvexDecomposition,
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcColliderIsProcessed;
#[derive(Debug, Clone, Reflect, Component, Default)]
#[reflect(Component, Default)]
pub struct RcJoint {
pub name: RdName,
pub category: RcJointCategory,
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcJointIsProcessed;
#[derive(Debug, Clone, Reflect, Default)]
pub enum RcJointCategory {
#[default]
Impulse,
Multibody,
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub enum RcJointKind {
Fixed {
parent: RdName,
child: RdName,
},
Revolute {
parent: RdName,
child: RdName,
axis: RdVector,
},
Prismatic {
parent: RdName,
child: RdName,
axis: RdVector,
},
Spherical {
parent: RdName,
child: RdName,
},
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component, Default)]
pub enum RcJointMotorControlConfig {
Position {
boost_ang_vel: f32,
norm_ang_vel: f32,
},
Velocity {
normal_vel: f32,
boost_vel: f32,
},
}
impl Default for RcJointMotorControlConfig {
fn default() -> Self {
Self::Position {
boost_ang_vel: PI, norm_ang_vel: FRAC_PI_2, }
}
}
#[derive(Debug, Clone, Reflect, Component, Default)]
#[reflect(Component, Default)]
pub struct RcRevoluteJointMotor {
pub model: RdMotorModel,
pub velocity: Option<RdMotorVelocity>,
pub position: Option<RdMotorPosition>,
pub max_force: Option<RdScaler>,
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcRevoluteJointLimits(pub RdJointLimits);
#[derive(Debug, Clone, Reflect, Component, Default)]
#[reflect(Component, Default)]
pub struct RcPrismaticJointMotor {
pub model: RdMotorModel,
pub velocity: Option<RdMotorVelocity>,
pub position: Option<RdMotorPosition>,
pub max_force: Option<RdScaler>,
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcPrismaticJointLimits(pub RdJointLimits);
#[derive(Debug, Clone, Reflect, Component, Default)]
#[reflect(Component, Default)]
pub struct RcSphericalJointMotor {
pub model_ang_x: RdMotorModel,
pub model_ang_y: RdMotorModel,
pub model_ang_z: RdMotorModel,
pub velocity_ang_x: Option<RdMotorVelocity>,
pub velocity_ang_y: Option<RdMotorVelocity>,
pub velocity_ang_z: Option<RdMotorVelocity>,
pub position_ang_x: Option<RdMotorPosition>,
pub position_ang_y: Option<RdMotorPosition>,
pub position_ang_z: Option<RdMotorPosition>,
pub max_force_ang_x: Option<RdScaler>,
pub max_force_ang_y: Option<RdScaler>,
pub max_force_ang_z: Option<RdScaler>,
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcSphericalJointLimits {
pub ang_x: Option<RdJointLimits>,
pub ang_y: Option<RdJointLimits>,
pub ang_z: Option<RdJointLimits>,
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcJointLocalAnchor1;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcJointLocalAnchor2;
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcIkTarget {
pub name: RdName,
}
#[derive(Debug, Clone, Reflect, Component)]
#[reflect(Component)]
pub struct RcIkTargetSource {
pub target: RdName,
}
#[derive(Debug, Clone, Reflect, Deref, DerefMut, Component)]
#[reflect(Component)]
pub struct RcIkAffectedLinks(pub Vec<RdName>);