use bstr::{BStr, BString};
use crate::Channel;
use mint::Vector3;
use smallvec::SmallVec;
use std::{
cmp::{Ordering, PartialEq, PartialOrd},
ffi::{CStr, CString},
fmt, mem,
ops::{Deref, DerefMut},
str,
};
#[derive(Clone, Debug, PartialEq)]
pub enum JointData {
Root {
name: JointName,
offset: Vector3<f32>,
channels: SmallVec<[Channel; 6]>,
},
Child {
name: JointName,
offset: Vector3<f32>,
channels: SmallVec<[Channel; 3]>,
end_site_offset: Option<Vector3<f32>>,
#[doc(hidden)]
private: JointPrivateData,
},
}
impl JointData {
#[inline]
pub fn is_root(&self) -> bool {
match *self {
JointData::Root { .. } => true,
_ => false,
}
}
#[inline]
pub fn is_child(&self) -> bool {
match *self {
JointData::Child { .. } => true,
_ => false,
}
}
#[inline]
pub fn name(&self) -> &BStr {
match *self {
JointData::Root { ref name, .. } | JointData::Child { ref name, .. } => name.as_ref(),
}
}
#[inline]
pub fn offset(&self) -> &Vector3<f32> {
match *self {
JointData::Child { ref offset, .. } | JointData::Root { ref offset, .. } => offset,
}
}
#[inline]
pub fn end_site(&self) -> Option<&Vector3<f32>> {
match *self {
JointData::Child {
ref end_site_offset,
..
} => end_site_offset.as_ref(),
_ => None,
}
}
#[inline]
pub fn has_end_site(&self) -> bool {
self.end_site().is_some()
}
#[inline]
pub fn channels(&self) -> &[Channel] {
match *self {
JointData::Child { ref channels, .. } => &channels[..],
JointData::Root { ref channels, .. } => &channels[..],
}
}
#[inline]
pub fn channels_mut(&mut self) -> &mut [Channel] {
match *self {
JointData::Child {
ref mut channels, ..
} => &mut channels[..],
JointData::Root {
ref mut channels, ..
} => &mut channels[..],
}
}
#[inline]
pub fn num_channels(&self) -> usize {
self.channels().len()
}
#[inline]
pub fn index(&self) -> usize {
self.private_data().map(|d| d.self_index).unwrap_or(0)
}
#[inline]
pub fn parent_index(&self) -> Option<usize> {
self.private_data().map(|d| d.parent_index)
}
#[inline]
pub(crate) fn private_data(&self) -> Option<&JointPrivateData> {
match *self {
JointData::Child { ref private, .. } => Some(private),
_ => None,
}
}
#[inline]
pub(crate) fn private_data_mut(&mut self) -> Option<&mut JointPrivateData> {
match *self {
JointData::Child {
ref mut private, ..
} => Some(private),
_ => None,
}
}
#[inline]
pub(crate) fn depth(&self) -> usize {
match *self {
JointData::Child { ref private, .. } => private.depth,
_ => 0,
}
}
#[inline]
pub(crate) fn empty_root() -> Self {
JointData::Root {
name: Default::default(),
offset: [0.0, 0.0, 0.0].into(),
channels: Default::default(),
}
}
#[inline]
pub(crate) fn empty_child() -> Self {
JointData::Child {
name: Default::default(),
offset: [0.0, 0.0, 0.0].into(),
channels: Default::default(),
end_site_offset: Default::default(),
private: JointPrivateData::empty(),
}
}
#[inline]
pub(crate) fn set_name<S: Into<JointName>>(&mut self, new_name: S) {
match *self {
JointData::Root { ref mut name, .. } => *name = new_name.into(),
JointData::Child { ref mut name, .. } => *name = new_name.into(),
}
}
pub(crate) fn set_offset(&mut self, new_offset: Vector3<f32>, is_site: bool) {
match *self {
JointData::Root { ref mut offset, .. } => *offset = new_offset,
JointData::Child {
ref mut offset,
ref mut end_site_offset,
..
} => {
if is_site {
*end_site_offset = Some(new_offset);
} else {
*offset = new_offset;
}
}
}
}
#[inline]
pub(crate) fn set_channels(&mut self, new_channels: SmallVec<[Channel; 6]>) {
match *self {
JointData::Root {
ref mut channels, ..
} => *channels = new_channels,
JointData::Child {
ref mut channels, ..
} => *channels = new_channels.iter().map(|c| *c).collect(),
}
}
}
pub type JointNameInner = SmallVec<[u8; mem::size_of::<String>()]>;
#[derive(Clone, Default, Eq, Hash, Ord)]
pub struct JointName(pub JointNameInner);
impl Deref for JointName {
type Target = JointNameInner;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for JointName {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<B: AsRef<[u8]>> PartialEq<B> for JointName {
#[inline]
fn eq(&self, rhs: &B) -> bool {
AsRef::<BStr>::as_ref(self) == rhs.as_ref()
}
}
impl<B: AsRef<[u8]>> PartialOrd<B> for JointName {
#[inline]
fn partial_cmp(&self, rhs: &B) -> Option<Ordering> {
AsRef::<BStr>::as_ref(self).partial_cmp(rhs.as_ref())
}
}
macro_rules! impl_from {
() => {};
(;) => {};
($t:ty; $($rest:tt)*) => {
impl From<$t> for JointName {
#[inline]
fn from(b: $t) -> Self {
JointName(b.bytes().collect())
}
}
impl_from!($($rest)*);
}
}
impl From<CString> for JointName {
#[inline]
fn from(s: CString) -> Self {
From::from(s.into_bytes())
}
}
impl From<&'_ CStr> for JointName {
#[inline]
fn from(s: &'_ CStr) -> Self {
From::from(s.to_bytes())
}
}
impl From<Vec<u8>> for JointName {
#[inline]
fn from(s: Vec<u8>) -> Self {
JointName(s.into_iter().collect())
}
}
impl From<&'_ [u8]> for JointName {
#[inline]
fn from(s: &'_ [u8]) -> Self {
From::from(BStr::new(s))
}
}
impl_from! {
String; &'_ str;
BString; &'_ BStr;
}
macro_rules! impl_as_ref {
($( $t:ty { ref => $method:path, mut => $mut_method:path } )*) => {
$(
impl AsRef<$t> for JointName {
#[inline]
fn as_ref(&self) -> &$t {
$method(&self.0[..])
}
}
impl AsMut<$t> for JointName {
#[inline]
fn as_mut(&mut self) -> &mut $t {
$mut_method(&mut self.0[..])
}
}
)*
}
}
impl_as_ref! {
BStr { ref => BStr::new, mut => BStr::new_mut }
[u8] { ref => AsRef::<[u8]>::as_ref, mut => AsMut::<[u8]>::as_mut }
}
impl From<JointNameInner> for JointName {
#[inline]
fn from(v: JointNameInner) -> Self {
JointName(v)
}
}
impl From<JointName> for JointNameInner {
#[inline]
fn from(j: JointName) -> Self {
j.0
}
}
impl fmt::Debug for JointName {
#[inline]
fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(AsRef::<BStr>::as_ref(self), fmtr)
}
}
impl fmt::Display for JointName {
#[inline]
fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(AsRef::<BStr>::as_ref(self), fmtr)
}
}
#[doc(hidden)]
#[derive(Clone, Eq, PartialEq)]
pub struct JointPrivateData {
pub(crate) self_index: usize,
pub(crate) parent_index: usize,
pub(crate) depth: usize,
}
impl JointPrivateData {
#[inline]
pub(crate) const fn new(self_index: usize, parent_index: usize, depth: usize) -> Self {
JointPrivateData {
self_index,
parent_index,
depth,
}
}
#[inline]
pub(crate) const fn empty() -> Self {
Self::new(0, 0, 0)
}
}
impl fmt::Debug for JointPrivateData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("JointPrivateData { .. }")
}
}
pub struct Joints<'a> {
pub(crate) joints: &'a [JointData],
pub(crate) current_joint: usize,
pub(crate) from_child: Option<usize>,
}
impl fmt::Debug for Joints<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Joints { .. }")
}
}
impl<'a> Joints<'a> {
pub(crate) fn iter_root(joints: &'a [JointData] ) -> Self {
Joints {
joints,
current_joint: 0,
from_child: None,
}
}
pub(crate) fn iter_children(joint: &Joint<'a>) -> Self {
let first_child = joint
.joints
.iter()
.find(|jd| {
if let Some(p) = jd.private_data() {
p.parent_index == joint.index
} else {
false
}
})
.map(JointData::index)
.unwrap();
Joints {
joints: joint.joints,
current_joint: joint.data().index(),
from_child: Some(first_child),
}
}
#[inline]
pub fn find_by_name(&mut self, joint_name: &str) -> Option<Joint<'a>> {
self.find(|b| b.data().name() == joint_name)
}
#[allow(unused)]
pub(crate) fn nth_child(joint: &Joint<'a>, child: usize) -> Option<usize> {
Joints::iter_children(joint)
.nth(child)
.map(|joint| joint.index)
}
}
impl<'a> Iterator for Joints<'a> {
type Item = Joint<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_joint >= self.joints.len() {
return None;
}
let joint = Some(Joint {
index: self.current_joint,
joints: self.joints,
});
if self.from_child.is_none() {
self.current_joint += 1;
} else {
unimplemented!()
}
joint
}
}
#[allow(unused)]
pub struct JointsMut<'a> {
pub(crate) joints: &'a mut [JointData],
pub(crate) current_joint: usize,
pub(crate) from_child: Option<usize>,
}
impl<'a> JointsMut<'a> {
pub(crate) fn iter_root(joints: &'a mut [JointData] ) -> Self {
JointsMut {
joints,
current_joint: 0,
from_child: None,
}
}
}
impl<'a> Iterator for JointsMut<'a> {
type Item = JointMut<'a>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
None
}
}
impl fmt::Debug for JointsMut<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("JointsMut { .. }")
}
}
pub struct Joint<'a> {
pub(crate) index: usize,
pub(crate) joints: &'a [JointData],
}
impl Joint<'_> {
#[inline]
pub fn parent(&self) -> Option<Joint<'_>> {
self.data().parent_index().map(|idx| Joint {
index: idx,
joints: self.joints,
})
}
#[inline]
pub fn children(&self) -> Joints<'_> {
Joints::iter_children(&self)
}
#[inline]
pub fn data(&self) -> &JointData {
&self.joints[self.index]
}
}
impl fmt::Debug for Joint<'_> {
#[inline]
fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
fmtr.debug_struct("Joint")
.field("index", &self.index)
.field("data", &self.data())
.finish()
}
}
pub struct JointMut<'a> {
pub(crate) index: usize,
pub(crate) joints: &'a mut [JointData],
}
impl<'a> JointMut<'a> {
#[inline]
pub fn data_mut(&mut self) -> &mut JointData {
&mut self.joints[self.index]
}
}