diff --git a/examples/skeleton.rs b/examples/skeleton.rs index 387a772..24064d4 100644 --- a/examples/skeleton.rs +++ b/examples/skeleton.rs @@ -18,7 +18,7 @@ use cushy::{ widgets::{slider::Slidable, Canvas}, Run, }; -use funnybones::{BoneId, BoneKind, Joint, JointId, Rotation, Skeleton, Vector}; +use funnybones::{Angle, BoneId, BoneKind, Coordinate, Joint, JointId, Skeleton}; fn main() { // begin rustme snippet: readme @@ -29,7 +29,7 @@ fn main() { let r_hip = skeleton.push_bone(BoneKind::Rigid { length: 0.5 }.with_label("r_hip")); // Connect the right hip to the spine. skeleton.push_joint(Joint::new( - Rotation::degrees(-90.), + Angle::degrees(-90.), spine.axis_a(), r_hip.axis_a(), )); @@ -46,7 +46,7 @@ fn main() { // Connect the right leg to the right hip. skeleton.push_joint(Joint::new( - Rotation::degrees(-90.), + Angle::degrees(-90.), r_hip.axis_b(), r_leg.axis_a(), )); @@ -54,7 +54,7 @@ fn main() { let r_foot = skeleton.push_bone(BoneKind::Rigid { length: 0.5 }.with_label("r_foot")); // Connect the right foot to the right leg. let r_ankle_id = skeleton.push_joint(Joint::new( - Rotation::degrees(90.), + Angle::degrees(90.), r_leg.axis_b(), r_foot.axis_a(), )); @@ -63,7 +63,7 @@ fn main() { // Create the left-half of our lower half. let l_hip = skeleton.push_bone(BoneKind::Rigid { length: 0.5 }.with_label("l_hip")); skeleton.push_joint(Joint::new( - Rotation::degrees(90.), + Angle::degrees(90.), spine.axis_a(), l_hip.axis_a(), )); @@ -76,13 +76,13 @@ fn main() { .with_label("l_leg"), ); skeleton.push_joint(Joint::new( - Rotation::degrees(90.), + Angle::degrees(90.), l_hip.axis_b(), l_leg.axis_a(), )); let l_foot = skeleton.push_bone(BoneKind::Rigid { length: 0.5 }.with_label("l_foot")); let l_ankle_id = skeleton.push_joint(Joint::new( - Rotation::degrees(-90.), + Angle::degrees(-90.), l_leg.axis_b(), l_foot.axis_a(), )); @@ -90,7 +90,7 @@ fn main() { // Create our two arms in the same fashion as our leg structure. let r_shoulder = skeleton.push_bone(BoneKind::Rigid { length: 0.5 }.with_label("r_shoulder")); skeleton.push_joint(Joint::new( - Rotation::degrees(-90.), + Angle::degrees(-90.), spine.axis_b(), r_shoulder.axis_a(), )); @@ -103,20 +103,20 @@ fn main() { .with_label("r_arm"), ); let r_arm_socket = skeleton.push_joint(Joint::new( - Rotation::degrees(-90.), + Angle::degrees(-90.), r_shoulder.axis_b(), r_arm.axis_a(), )); let r_hand = skeleton.push_bone(BoneKind::Rigid { length: 0.3 }.with_label("r_hand")); let r_wrist_id = skeleton.push_joint(Joint::new( - Rotation::degrees(175.), + Angle::degrees(175.), r_arm.axis_b(), r_hand.axis_a(), )); let l_shoulder = skeleton.push_bone(BoneKind::Rigid { length: 0.5 }.with_label("l_shoulder")); skeleton.push_joint(Joint::new( - Rotation::degrees(90.), + Angle::degrees(90.), spine.axis_b(), l_shoulder.axis_a(), )); @@ -129,13 +129,13 @@ fn main() { .with_label("l_arm"), ); let l_arm_socket = skeleton.push_joint(Joint::new( - Rotation::degrees(90.), + Angle::degrees(90.), l_shoulder.axis_b(), l_arm.axis_a(), )); let l_hand = skeleton.push_bone(BoneKind::Rigid { length: 0.3 }.with_label("l_hand")); let l_wrist_id = skeleton.push_joint(Joint::new( - Rotation::degrees(-175.), + Angle::degrees(-175.), l_arm.axis_b(), l_hand.axis_a(), )); @@ -143,7 +143,7 @@ fn main() { // Finally, create a bone to represent our head. let head = skeleton.push_bone(BoneKind::Rigid { length: 0.5 }.with_label("head")); let neck = skeleton.push_joint(Joint::new( - Rotation::degrees(180.), + Angle::degrees(180.), spine.axis_b(), head.axis_a(), )); @@ -255,7 +255,7 @@ fn joint_widget(label: &str, skeleton: &Dynamic, joint: JointId) -> im } }) .persist(); - let angle_slider = angle.slider_between(Rotation::degrees(0.), Rotation::degrees(359.9)); + let angle_slider = angle.slider_between(Angle::degrees(0.), Angle::degrees(359.9)); label.and(angle_slider).into_rows().contain() } @@ -276,7 +276,7 @@ fn bone_widget( move |y| { let mut skeleton = skeleton.lock(); let current_end = skeleton[bone].desired_end().unwrap_or_default(); - skeleton[bone].set_desired_end(Some(Vector::new(current_end.x, *y))); + skeleton[bone].set_desired_end(Some(Coordinate::new(current_end.x, *y))); } }) .persist(); @@ -286,7 +286,7 @@ fn bone_widget( move |x| { let mut skeleton = skeleton.lock(); let current_end = skeleton[bone].desired_end().unwrap_or_default(); - skeleton[bone].set_desired_end(Some(Vector::new(*x, current_end.y))); + skeleton[bone].set_desired_end(Some(Coordinate::new(*x, current_end.y))); } }) .persist(); diff --git a/src/animation.rs b/src/animation.rs index 02e571e..0164e3b 100644 --- a/src/animation.rs +++ b/src/animation.rs @@ -9,7 +9,7 @@ use std::{ use easing_function::{easings::StandardEasing, Easing}; -use crate::{BoneId, JointId, Rotation, Skeleton, Vector}; +use crate::{BoneId, JointId, Angle, Skeleton, Coordinate}; #[derive(Default, Debug, PartialEq, Clone)] pub struct Animation(Arc); @@ -166,8 +166,8 @@ impl From for Change { #[derive(Debug, PartialEq, Clone, Copy)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ChangeKind { - Bone { bone: BoneId, position: Vector }, - Joint { joint: JointId, rotation: Rotation }, + Bone { bone: BoneId, position: Coordinate }, + Joint { joint: JointId, rotation: Angle }, } impl ChangeKind { @@ -178,8 +178,8 @@ impl ChangeKind { } enum OriginalProperty { - Rotation(Rotation), - Vector(Vector), + Rotation(Angle), + Vector(Coordinate), } pub struct RunningAnimation { @@ -290,16 +290,16 @@ impl Lerp for f32 { } } -impl Lerp for Vector { +impl Lerp for Coordinate { fn lerp(self, target: Self, percent: f32) -> Self { - Vector::new( + Coordinate::new( self.x.lerp(target.x, percent), self.y.lerp(target.y, percent), ) } } -impl Lerp for Rotation { +impl Lerp for Angle { fn lerp(self, target: Self, percent: f32) -> Self { let delta_neg = self.radians - target.radians; let delta_pos = target.radians - self.radians; diff --git a/src/cushy.rs b/src/cushy.rs index 49a1d0c..7f2a44e 100644 --- a/src/cushy.rs +++ b/src/cushy.rs @@ -2,17 +2,17 @@ use cushy::figures::Ranged; -use crate::{Rotation, Vector}; +use crate::{Angle, Coordinate}; pub mod skeleton_canvas; -impl cushy::animation::PercentBetween for Rotation { +impl cushy::animation::PercentBetween for Angle { fn percent_between(&self, min: &Self, max: &Self) -> cushy::animation::ZeroToOne { self.radians.percent_between(&min.radians, &max.radians) } } -impl cushy::animation::LinearInterpolate for Rotation { +impl cushy::animation::LinearInterpolate for Angle { fn lerp(&self, target: &Self, percent: f32) -> Self { Self { radians: self.radians.lerp(&target.radians, percent), @@ -20,19 +20,19 @@ impl cushy::animation::LinearInterpolate for Rotation { } } -impl cushy::figures::IntoComponents for Vector { +impl cushy::figures::IntoComponents for Coordinate { fn into_components(self) -> (f32, f32) { (self.x, self.y) } } -impl cushy::figures::FromComponents for Vector { +impl cushy::figures::FromComponents for Coordinate { fn from_components(components: (f32, f32)) -> Self { Self::new(components.0, components.1) } } -impl Ranged for Rotation { +impl Ranged for Angle { const MIN: Self = Self::MIN; const MAX: Self = Self::MAX; } diff --git a/src/cushy/skeleton_canvas.rs b/src/cushy/skeleton_canvas.rs index 8c1e09e..fdecee9 100644 --- a/src/cushy/skeleton_canvas.rs +++ b/src/cushy/skeleton_canvas.rs @@ -1,7 +1,7 @@ #![allow(missing_docs)] use core::f32; -use crate::{BoneEnd, BoneId, JointId, Rotation, Skeleton, Vector}; +use crate::{BoneEnd, BoneId, JointId, Angle, Skeleton, Coordinate}; use cushy::{ context::{EventContext, GraphicsContext, LayoutContext}, figures::{ @@ -54,14 +54,14 @@ impl SkeletonCanvas { self } - fn vector_position(&self, vector: Vector) -> Point { + fn vector_position(&self, vector: Coordinate) -> Point { (vector * self.scale).to_vec::>().map(Px::from) + self.offset } - fn position_to_vector(&self, position: Point) -> Vector { + fn position_to_vector(&self, position: Point) -> Coordinate { (position - self.offset) .map(FloatConversion::into_float) - .to_vec::() + .to_vec::() / self.scale } } @@ -77,21 +77,21 @@ impl Widget for SkeletonCanvas { skeleton.solve(); let root_start = skeleton.bones()[0].start(); let (min, max) = skeleton.bones().iter().fold( - (Vector::new(f32::MAX, f32::MAX), Vector::default()), + (Coordinate::new(f32::MAX, f32::MAX), Coordinate::default()), |(min, max), bone| { let start = bone.start() - root_start; let end = bone.end() - root_start; ( - Vector::new(min.x.min(start.x).min(end.x), min.y.min(start.y).min(end.y)), - Vector::new(max.x.max(start.x).max(end.x), max.y.max(start.y).max(end.y)), + Coordinate::new(min.x.min(start.x).min(end.x), min.y.min(start.y).min(end.y)), + Coordinate::new(max.x.max(start.x).max(end.x), max.y.max(start.y).max(end.y)), ) }, ); let skeleton_extent = - Vector::new(min.x.abs().max(max.x.abs()), min.y.abs().max(max.y.abs())); + Coordinate::new(min.x.abs().max(max.x.abs()), min.y.abs().max(max.y.abs())); - let middle = context.gfx.size().into_float().to_vec::() / 2.; + let middle = context.gfx.size().into_float().to_vec::() / 2.; let height_ratio = middle.y / skeleton_extent.y; let width_ratio = middle.x / skeleton_extent.x; let zero_width = width_ratio.is_nan(); @@ -300,7 +300,7 @@ impl Widget for SkeletonCanvas { } } -fn distance_to_line(test: Vector, p1: Vector, p2: Vector) -> f32 { +fn distance_to_line(test: Coordinate, p1: Coordinate, p2: Coordinate) -> f32 { let delta = p2 - p1; let segment_length = delta.magnitude(); @@ -328,11 +328,11 @@ pub enum Target { #[derive(Debug)] struct DragInfo { target: Target, - last: Vector, + last: Coordinate, } #[derive(Clone, Copy, Debug, PartialEq)] pub enum SkeletonMutation { - SetDesiredEnd { bone: BoneId, end: Vector }, - SetJointRotation { joint: JointId, rotation: Rotation }, + SetDesiredEnd { bone: BoneId, end: Coordinate }, + SetJointRotation { joint: JointId, rotation: Angle }, } diff --git a/src/funnybones.rs b/src/funnybones.rs index 9ebf937..758b960 100644 --- a/src/funnybones.rs +++ b/src/funnybones.rs @@ -10,7 +10,7 @@ use cushy::{ }; use funnybones::{ cushy::skeleton_canvas::{SkeletonCanvas, SkeletonMutation}, - BoneAxis, BoneId, BoneKind, Joint, JointId, LabeledBoneKind, Rotation, Skeleton, Vector, + BoneAxis, BoneId, BoneKind, Joint, JointId, LabeledBoneKind, Angle, Skeleton, Coordinate, }; #[derive(Default, Eq, PartialEq, Debug, Clone, Copy)] @@ -200,11 +200,11 @@ impl EditingSkeleton { struct SkeletalBone { label: Dynamic, joint_label: Dynamic, - joint_angle: Dynamic, + joint_angle: Dynamic, length: Dynamic, jointed: Dynamic>, inverse: Dynamic, - desired_end: Dynamic>, + desired_end: Dynamic>, connected_bones: Dynamic>, } @@ -228,7 +228,7 @@ impl Default for SkeletalBone { fn default() -> Self { Self { joint_label: Dynamic::default(), - joint_angle: Dynamic::new(Rotation::degrees(90.)), + joint_angle: Dynamic::new(Angle::degrees(90.)), label: Dynamic::default(), length: Dynamic::new(1.), jointed: Dynamic::default(), diff --git a/src/lib.rs b/src/lib.rs index 72b7fb5..7955dbf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,14 +19,14 @@ mod serde; /// A two dimensionsional offset/measurement. #[derive(Default, Clone, Copy, PartialEq, Debug)] #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] -pub struct Vector { +pub struct Coordinate { /// The x-axis component of this vector. pub x: f32, /// The y-axis component of this vector. pub y: f32, } -impl Vector { +impl Coordinate { /// Returns a new vector from the x and y values. #[must_use] pub const fn new(x: f32, y: f32) -> Self { @@ -50,12 +50,12 @@ impl Vector { /// Returns the angle formed a line passing through 0,0 towards this vector. #[must_use] - pub fn as_rotation(self) -> Rotation { - Rotation::radians(self.y.atan2(self.x)) + pub fn as_rotation(self) -> Angle { + Angle::radians(self.y.atan2(self.x)) } } -impl Add for Vector { +impl Add for Coordinate { type Output = Self; fn add(self, rhs: Self) -> Self::Output { @@ -66,7 +66,7 @@ impl Add for Vector { } } -impl Sub for Vector { +impl Sub for Coordinate { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { @@ -77,7 +77,7 @@ impl Sub for Vector { } } -impl Mul for Vector { +impl Mul for Coordinate { type Output = Self; fn mul(self, rhs: f32) -> Self::Output { @@ -88,7 +88,7 @@ impl Mul for Vector { } } -impl Div for Vector { +impl Div for Coordinate { type Output = Self; fn div(self, rhs: f32) -> Self::Output { @@ -99,20 +99,21 @@ impl Div for Vector { } } -/// A value representing a rotation between no rotation and a full rotation. +/// A value representing a direction. #[derive(Clone, Copy, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] -pub struct Rotation { +pub struct Angle { radians: f32, } -impl Rotation { +impl Angle { /// The minimum rotation represented by this type. pub const MIN: Self = Self { radians: 0. }; /// The maximum rotation represented by this type. pub const MAX: Self = Self { radians: PI * 2. - f32::EPSILON, }; + /// Returns a rotation representing the given radians. #[must_use] pub fn radians(radians: f32) -> Self { @@ -153,27 +154,39 @@ impl Rotation { } self } + + /// Returns the cosine of this angle. + #[must_use] + pub fn cos(self) -> f32 { + self.radians.cos() + } + + /// Returns the sine of this angle. + #[must_use] + pub fn sin(self) -> f32 { + self.radians.sin() + } } -impl Debug for Rotation { +impl Debug for Angle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(self, f) } } -impl Display for Rotation { +impl Display for Angle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}°", self.to_degrees()) } } -impl Default for Rotation { +impl Default for Angle { fn default() -> Self { Self { radians: 0. } } } -impl Add for Rotation { +impl Add for Angle { type Output = Self; fn add(self, rhs: Self) -> Self::Output { @@ -181,7 +194,7 @@ impl Add for Rotation { } } -impl Sub for Rotation { +impl Sub for Angle { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { @@ -189,7 +202,7 @@ impl Sub for Rotation { } } -impl Neg for Rotation { +impl Neg for Angle { type Output = Self; fn neg(self) -> Self::Output { @@ -197,6 +210,60 @@ impl Neg for Rotation { } } +/// A 2D Euclidean vector. +#[derive(Clone, Copy, PartialEq, Debug)] +pub struct Vector { + /// The length of the vector. + pub magnitude: f32, + /// The direction the vector is heading. + pub direction: Angle, +} + +impl Vector { + /// Returns a new vector for the given magnitude and direction. + #[must_use] + pub const fn new(magnitude: f32, direction: Angle) -> Self { + Self { + magnitude, + direction, + } + } +} + +impl From for Coordinate { + fn from(vec: Vector) -> Self { + Self { + x: vec.magnitude * vec.direction.sin(), + y: -vec.magnitude * vec.direction.cos(), + } + } +} + +impl From for Vector { + fn from(pt: Coordinate) -> Self { + Self { + direction: pt.as_rotation(), + magnitude: pt.magnitude(), + } + } +} + +impl Add for Coordinate { + type Output = Self; + + fn add(self, rhs: Vector) -> Self::Output { + self + Coordinate::from(rhs) + } +} + +impl Sub for Coordinate { + type Output = Self; + + fn sub(self, rhs: Vector) -> Self::Output { + self - Coordinate::from(rhs) + } +} + /// A representation of a bone structure inside of a [`Skeleton`]. #[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] @@ -292,7 +359,7 @@ impl Skeleton { let bone = bone.into(); let id = BoneId(u16::try_from(self.bones.len()).expect("too many bones")); if id == BoneId(0) { - let joint = self.push_joint(Joint::new(Rotation::default(), id.axis_a(), id.axis_a())); + let joint = self.push_joint(Joint::new(Angle::default(), id.axis_a(), id.axis_a())); self.initial_joint = Some(joint); self.connections.insert(id.axis_a(), vec![joint]); } @@ -308,9 +375,9 @@ impl Skeleton { generation: self.generation, label, kind: bone.kind, - start: Vector::default(), + start: Coordinate::default(), joint_pos: None, - end: Vector::default(), + end: Coordinate::default(), desired_end: None, }); id @@ -365,19 +432,19 @@ impl Skeleton { } /// Sets a translation to be applied to the entire skeleton. - pub fn set_translation(&mut self, translation: Vector) { + pub fn set_translation(&mut self, translation: Coordinate) { let bone = self.bones.first_mut().expect("root bone must be defined"); bone.start = translation; } /// Returns the translation applied to the entire skeleton. #[must_use] - pub fn translation(&self) -> Vector { + pub fn translation(&self) -> Coordinate { self.bones.first().expect("root bone must be defined").start } /// Sets a base rotation to apply to the entire skeleton. - pub fn set_rotation(&mut self, rotation: Rotation) { + pub fn set_rotation(&mut self, rotation: Angle) { let joint = self.initial_joint.expect("root bone must be defined"); let joint = &mut self[joint]; joint.angle = rotation; @@ -385,7 +452,7 @@ impl Skeleton { /// Returns the base rotation being applied to the entire skeleton. #[must_use] - pub fn rotation(&self) -> Rotation { + pub fn rotation(&self) -> Angle { let joint = self.initial_joint.expect("root bone must be defined"); self[joint].angle } @@ -401,7 +468,7 @@ impl Skeleton { fn solve_axis(&mut self, axis: BoneAxis) { let mut axis_solved = HashSet::new(); - let mut to_solve = vec![(axis, None, Rotation::default(), false)]; + let mut to_solve = vec![(axis, None, Angle::default(), false)]; while let Some((axis, current_position, current_rotation, inverse_root)) = to_solve.pop() { if !axis_solved.insert(axis) { continue; @@ -431,7 +498,7 @@ impl Skeleton { }; let angle = if inverse_root { - Rotation::radians(PI) - joint.angle + Angle::radians(PI) - joint.angle } else { joint.angle }; @@ -454,7 +521,7 @@ impl Skeleton { // driven by an input angle, but a fixed correction amount // seems to be the correct answer. Without this, a joint // angle of 0 sticks out at a perpendicular angle. - next_rotation = rotation + Rotation::radians(PI / 2.); + next_rotation = rotation + Angle::radians(PI / 2.); } if axis == BoneId(0).axis_a() && other_axis == axis { @@ -474,20 +541,14 @@ impl Skeleton { } } -fn next_point(mut point: Vector, angle: Rotation, length: f32) -> Vector { - point.x += length * angle.radians.sin(); - point.y -= length * angle.radians.cos(); - point -} - fn determine_end_position( - start: Vector, - desired_end: Option, - angle: Rotation, + start: Coordinate, + desired_end: Option, + angle: Angle, bone: &BoneKind, -) -> (Vector, Option) { +) -> (Coordinate, Option) { match bone { - BoneKind::Rigid { length } => (next_point(start, angle, *length), None), + BoneKind::Rigid { length } => (start + Vector::new(*length, angle), None), BoneKind::Jointed { start_length, end_length, @@ -495,7 +556,7 @@ fn determine_end_position( } => { if let Some(desired_end) = desired_end { let delta = desired_end - start; - let desired_angle = delta.as_rotation() + Rotation::radians(PI / 2.); + let desired_angle = delta.as_rotation() + Angle::radians(PI / 2.); let distance = delta.magnitude(); let full_length = start_length + end_length; let minimum_size = (start_length - end_length).abs(); @@ -509,7 +570,7 @@ fn determine_end_position( let end = if capped { // We need to cap the end point along this sloped line - next_point(start, desired_angle, desired_length) + start + Vector::new(desired_length, desired_angle) } else { // The end position is valid desired_end @@ -526,8 +587,8 @@ fn determine_end_position( (end, Some(joint)) } else { - let joint = next_point(start, angle, *start_length); - let end = next_point(joint, angle, *end_length); + let joint = start + Vector::new(*start_length, angle); + let end = joint + Vector::new(*end_length, angle); (end, Some(joint)) } } @@ -536,22 +597,22 @@ fn determine_end_position( fn get_third_point( inverse: bool, - start: Vector, + start: Coordinate, distance: f32, - hyp_angle: Rotation, + hyp_angle: Angle, first: f32, second: f32, -) -> Vector { +) -> Coordinate { let hyp = distance; let first_angle = ((first * first + hyp * hyp - second * second) / (2. * first * hyp)).acos(); if first_angle.is_nan() { - next_point(start, hyp_angle, first) + start + Vector::new(first, hyp_angle) } else { let first_angle = hyp_angle - - Rotation { + - Angle { radians: if inverse { -first_angle } else { first_angle }, }; - next_point(start, first_angle, first) + start + Vector::new(first, first_angle) } } @@ -611,10 +672,10 @@ pub struct Bone { generation: usize, label: Option, kind: BoneKind, - start: Vector, - joint_pos: Option, - end: Vector, - desired_end: Option, + start: Coordinate, + joint_pos: Option, + end: Coordinate, + desired_end: Option, } impl Bone { @@ -636,32 +697,32 @@ impl Bone { /// root of the skeleton. /// /// This setting only impacts [`BoneKind::Jointed`] bones. - pub fn set_desired_end(&mut self, end: Option) { + pub fn set_desired_end(&mut self, end: Option) { self.desired_end = end; } /// Returns the location this bone is being aimed towards. #[must_use] - pub const fn desired_end(&self) -> Option { + pub const fn desired_end(&self) -> Option { self.desired_end } /// Returns the solved start position of this bone. #[must_use] - pub const fn start(&self) -> Vector { + pub const fn start(&self) -> Coordinate { self.start } /// Returns the solved end position of this bone. #[must_use] - pub const fn end(&self) -> Vector { + pub const fn end(&self) -> Coordinate { self.end } /// If this is a [`BoneKind::Jointed`] bone, returns the solved position of /// the joint. #[must_use] - pub const fn solved_joint(&self) -> Option { + pub const fn solved_joint(&self) -> Option { self.joint_pos } @@ -679,8 +740,8 @@ pub struct Joint { label: Option, bone_a: BoneAxis, bone_b: BoneAxis, - calculated_position: Vector, - angle: Rotation, + calculated_position: Coordinate, + angle: Angle, } impl Joint { @@ -692,13 +753,13 @@ impl Joint { /// Returns a new joint formed by joining `bone_a` and `bone_b` at `angle`. #[must_use] - pub const fn new(angle: Rotation, bone_a: BoneAxis, bone_b: BoneAxis) -> Self { + pub const fn new(angle: Angle, bone_a: BoneAxis, bone_b: BoneAxis) -> Self { Self { id: JointId(0), label: None, bone_a, bone_b, - calculated_position: Vector::new(0., 0.), + calculated_position: Coordinate::new(0., 0.), angle, } } @@ -740,13 +801,13 @@ impl Joint { /// /// This setting is ignored if the bone furthest from the root of the joint /// is a [`BoneKind::Jointed`] bone. - pub fn set_angle(&mut self, angle: Rotation) { + pub fn set_angle(&mut self, angle: Angle) { self.angle = angle; } /// Returns the rotation of this joint. #[must_use] - pub const fn angle(&self) -> Rotation { + pub const fn angle(&self) -> Angle { self.angle } } @@ -820,14 +881,14 @@ impl BoneEnd { #[allow(clippy::cast_possible_truncation)] fn rotation() { assert_eq!( - (Rotation::degrees(90.) + Rotation::degrees(180.)) + (Angle::degrees(90.) + Angle::degrees(180.)) .normalized() .to_degrees() .round() as i32, 270, ); assert_eq!( - (Rotation::degrees(90.) + Rotation::degrees(-180.)) + (Angle::degrees(90.) + Angle::degrees(-180.)) .normalized() .to_degrees() .round() as i32, diff --git a/src/serde.rs b/src/serde.rs index 3e6e42f..513298a 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -6,7 +6,7 @@ use serde::{ Deserialize, Serialize, }; -use crate::{Bone, BoneAxis, BoneKind, Joint, Rotation, Skeleton, Vector}; +use crate::{Bone, BoneAxis, BoneKind, Joint, Angle, Skeleton, Coordinate}; impl Serialize for Skeleton { fn serialize(&self, serializer: S) -> Result @@ -106,7 +106,7 @@ struct DeserializedBone { label: String, kind: BoneKind, #[serde(default)] - target: Option, + target: Option, } impl Serialize for Joint { @@ -130,7 +130,7 @@ impl Serialize for Joint { struct DeserializedJoint { from: BoneAxis, to: BoneAxis, - angle: Rotation, + angle: Angle, #[serde(default)] label: String, } @@ -145,7 +145,7 @@ fn roundtrip() { inverse: true, }); let joint = s.push_joint(Joint::new( - Rotation::radians(0.), + Angle::radians(0.), spine.axis_a(), other.axis_b(), )); @@ -153,5 +153,5 @@ fn roundtrip() { let deserialized: Skeleton = dbg!(pot::from_slice(&serialized).unwrap()); assert_eq!(deserialized[spine].label(), "spine"); assert_eq!(deserialized[other].label(), ""); - assert_eq!(deserialized[joint].angle(), Rotation::radians(0.)); + assert_eq!(deserialized[joint].angle(), Angle::radians(0.)); }