diff --git a/examples/skeleton.rs b/examples/skeleton.rs index 3092d88..387a772 100644 --- a/examples/skeleton.rs +++ b/examples/skeleton.rs @@ -1,4 +1,5 @@ //! A basic 2d humanoid skeleton with sliders powered by Cushy. +#![allow(clippy::too_many_lines)] use core::f32; use std::ops::RangeInclusive; diff --git a/src/lib.rs b/src/lib.rs index 30606ae..a8eec77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,11 @@ #![doc = include_str!(".crate-docs.md")] use std::{ + borrow::Borrow, collections::{HashMap, HashSet}, f32::consts::PI, fmt::{Debug, Display}, - ops::{Add, Index, IndexMut, Neg, Sub}, + ops::{Add, Deref, Index, IndexMut, Neg, Sub}, sync::Arc, }; @@ -226,6 +227,29 @@ impl From for LabeledBoneKind { } } +#[derive(Clone, Eq, PartialEq, Hash, Debug)] +struct ArcString(Arc); + +impl PartialEq for ArcString { + fn eq(&self, other: &str) -> bool { + &**self == other + } +} + +impl Deref for ArcString { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Borrow for ArcString { + fn borrow(&self) -> &str { + self + } +} + /// A collection of [`Bone`]s. connected by [`Joint`]s. #[derive(Default, Debug)] pub struct Skeleton { @@ -234,8 +258,8 @@ pub struct Skeleton { joints: Vec, connections: HashMap>, generation: usize, - bones_by_label: HashMap, BoneId>, - joints_by_label: HashMap, JointId>, + bones_by_label: HashMap, + joints_by_label: HashMap, } impl Skeleton { @@ -256,7 +280,7 @@ impl Skeleton { let label = if bone.label.is_empty() { None } else { - let label = Arc::new(bone.label); + let label = ArcString(Arc::new(bone.label)); self.bones_by_label.insert(label.clone(), id); Some(label) }; @@ -289,6 +313,18 @@ impl Skeleton { id } + /// Finds an existing [`Joint`] by its label. + #[must_use] + pub fn find_joint_by_label(&self, label: &str) -> Option { + self.joints_by_label.get(label).copied() + } + + /// Finds an existing [`Bone`] by its label. + #[must_use] + pub fn find_bone_by_label(&self, label: &str) -> Option { + self.bones_by_label.get(label).copied() + } + /// Sets a translation to be applied to the entire skeleton. pub fn set_translation(&mut self, translation: Vector) { let bone = self.bones.first_mut().expect("root bone must be defined"); @@ -545,7 +581,7 @@ impl BoneAxis { #[derive(Debug)] pub struct Bone { generation: usize, - label: Option>, + label: Option, kind: BoneKind, start: Vector, joint_pos: Option, @@ -599,7 +635,7 @@ impl Bone { /// A connection between two bones. #[derive(Debug)] pub struct Joint { - label: Option>, + label: Option, bone_a: BoneAxis, bone_b: BoneAxis, calculated_position: Vector, @@ -624,7 +660,7 @@ impl Joint { pub fn with_label(mut self, label: impl Into) -> Self { let label = label.into(); if !label.is_empty() { - self.label = Some(Arc::new(label)); + self.label = Some(ArcString(Arc::new(label))); } self }