diff --git a/editor/src/inspector/handlers/node/joint.rs b/editor/src/inspector/handlers/node/joint.rs index 25d4083ad..84419c644 100644 --- a/editor/src/inspector/handlers/node/joint.rs +++ b/editor/src/inspector/handlers/node/joint.rs @@ -45,13 +45,21 @@ pub fn handle_joint_property_changed( pub fn handle_ball_joint(args: &PropertyChanged, handle: Handle) -> Option { handle_property_changed!(args, handle, - BallJoint::LIMITS_ANGLES => SetBallJointLimitsCommand + BallJoint::X_LIMITS_ANGLES => SetBallJointXLimitsCommand, + BallJoint::X_LIMITS_ENABLED => SetBallJointXLimitsEnabledCommand, + + BallJoint::Y_LIMITS_ANGLES => SetBallJointYLimitsCommand, + BallJoint::Y_LIMITS_ENABLED => SetBallJointYLimitsEnabledCommand, + + BallJoint::Z_LIMITS_ANGLES => SetBallJointZLimitsCommand, + BallJoint::Z_LIMITS_ENABLED => SetBallJointZLimitsEnabledCommand ) } pub fn handle_revolute_joint(args: &PropertyChanged, handle: Handle) -> Option { handle_property_changed!(args, handle, - RevoluteJoint::LIMITS => SetRevoluteJointLimitsCommand + RevoluteJoint::LIMITS => SetRevoluteJointLimitsCommand, + RevoluteJoint::LIMITS_ENABLED => SetRevoluteJointLimitsEnabledCommand ) } @@ -60,7 +68,8 @@ pub fn handle_prismatic_joint( handle: Handle, ) -> Option { handle_property_changed!(args, handle, - PrismaticJoint::LIMITS => SetPrismaticJointLimitsCommand + PrismaticJoint::LIMITS => SetPrismaticJointLimitsCommand, + PrismaticJoint::LIMITS_ENABLED => SetPrismaticJointLimitsEnabledCommand ) } diff --git a/editor/src/inspector/handlers/node/joint2d.rs b/editor/src/inspector/handlers/node/joint2d.rs index 86297d91b..6fb4a8e7c 100644 --- a/editor/src/inspector/handlers/node/joint2d.rs +++ b/editor/src/inspector/handlers/node/joint2d.rs @@ -43,7 +43,8 @@ pub fn handle_joint2d_property_changed( pub fn handle_ball_joint(args: &PropertyChanged, handle: Handle) -> Option { handle_property_changed!(args, handle, - BallJoint::LIMITS_ANGLES => SetBallJointLimitsCommand + BallJoint::LIMITS_ANGLES => SetBallJointLimitsCommand, + BallJoint::LIMITS_ENABLED => SetBallJointLimitsEnabledCommand ) } @@ -52,7 +53,8 @@ pub fn handle_prismatic_joint( handle: Handle, ) -> Option { handle_property_changed!(args, handle, - PrismaticJoint::LIMITS => SetPrismaticJointLimitsCommand + PrismaticJoint::LIMITS => SetPrismaticJointLimitsCommand, + PrismaticJoint::LIMITS_ENABLED => SetPrismaticJointLimitsEnabledCommand ) } diff --git a/editor/src/scene/commands/joint.rs b/editor/src/scene/commands/joint.rs index 558ba0981..f98af5572 100644 --- a/editor/src/scene/commands/joint.rs +++ b/editor/src/scene/commands/joint.rs @@ -23,9 +23,18 @@ macro_rules! define_joint_variant_command { } define_joint_variant_command! { - SetBallJointLimitsCommand(Range): BallJoint, limits_angles, "Set Ball Joint Limits"; + SetBallJointXLimitsCommand(Range): BallJoint, x_limits_angles, "Set Ball Joint X Limits"; + SetBallJointXLimitsEnabledCommand(bool): BallJoint, x_limits_enabled, "Set Ball Joint X Limits Enabled"; + SetBallJointYLimitsCommand(Range): BallJoint, y_limits_angles, "Set Ball Joint Y Limits"; + SetBallJointYLimitsEnabledCommand(bool): BallJoint, y_limits_enabled, "Set Ball Joint Y Limits Enabled"; + SetBallJointZLimitsCommand(Range): BallJoint, z_limits_angles, "Set Ball Joint Z Limits"; + SetBallJointZLimitsEnabledCommand(bool): BallJoint, z_limits_enabled, "Set Ball Joint Z Limits Enabled"; + SetRevoluteJointLimitsCommand(Range): RevoluteJoint, limits, "Set Revolute Joint Limits"; + SetRevoluteJointLimitsEnabledCommand(bool): RevoluteJoint, limits_enabled, "Set Revolute Joint Limits Enabled"; + SetPrismaticJointLimitsCommand(Range): PrismaticJoint, limits, "Set Prismatic Joint Limits"; + SetPrismaticJointLimitsEnabledCommand(bool): PrismaticJoint, limits_enabled, "Set Prismatic Joint Limits Enabled"; } define_swap_command! { diff --git a/editor/src/scene/commands/joint2d.rs b/editor/src/scene/commands/joint2d.rs index 5c24b01d8..b24dfd788 100644 --- a/editor/src/scene/commands/joint2d.rs +++ b/editor/src/scene/commands/joint2d.rs @@ -24,7 +24,10 @@ macro_rules! define_joint_variant_command { define_joint_variant_command! { SetBallJointLimitsCommand(Range): BallJoint, limits_angles, "Set Ball Joint Limits"; + SetBallJointLimitsEnabledCommand(bool): BallJoint, limits_enabled, "Set Ball Joint Limits Enabled"; + SetPrismaticJointLimitsCommand(Range): PrismaticJoint, limits, "Set Prismatic Joint Limits"; + SetPrismaticJointLimitsEnabledCommand(bool): PrismaticJoint, limits_enabled, "Set Prismatic Joint Limits"; } define_swap_command! { diff --git a/src/scene/dim2/joint.rs b/src/scene/dim2/joint.rs index 463cde02e..e3ff107e1 100644 --- a/src/scene/dim2/joint.rs +++ b/src/scene/dim2/joint.rs @@ -31,7 +31,13 @@ use std::{ /// pendulum, etc. #[derive(Clone, Debug, Visit, PartialEq, Inspect)] pub struct BallJoint { - /// The maximum angle allowed between the two limit axes in world-space. + /// Whether angular limits are enabled or not. Default is `false` + #[inspect(description = "Whether angular limits are enabled or not.")] + #[visit(optional)] // Backward compatibility + pub limits_enabled: bool, + + /// Allowed angles range for the joint (in radians). + #[inspect(description = "Allowed angles range for the joint (in radians).")] #[visit(optional)] // Backward compatibility pub limits_angles: Range, } @@ -39,6 +45,7 @@ pub struct BallJoint { impl Default for BallJoint { fn default() -> Self { Self { + limits_enabled: false, limits_angles: -std::f32::consts::PI..std::f32::consts::PI, } } @@ -53,7 +60,15 @@ pub struct FixedJoint; /// translations along one axis. The real world example is a sliders that used to support drawers. #[derive(Clone, Debug, Visit, PartialEq, Inspect)] pub struct PrismaticJoint { - /// The min an max relative position of the attached bodies along this joint's axis. + /// Whether linear limits along local X axis of the joint are enabled or not. Default is `false` + #[inspect( + description = "Whether linear limits along local X axis of the joint are enabled or not." + )] + #[visit(optional)] // Backward compatibility + pub limits_enabled: bool, + + /// Allowed linear distance range along local X axis of the joint. + #[inspect(description = "Allowed linear distance range along local X axis of the joint.")] #[visit(optional)] // Backward compatibility pub limits: Range, } @@ -61,6 +76,7 @@ pub struct PrismaticJoint { impl Default for PrismaticJoint { fn default() -> Self { Self { + limits_enabled: false, limits: -std::f32::consts::PI..std::f32::consts::PI, } } diff --git a/src/scene/dim2/physics.rs b/src/scene/dim2/physics.rs index 8bd088372..e7bc167ee 100644 --- a/src/scene/dim2/physics.rs +++ b/src/scene/dim2/physics.rs @@ -1,18 +1,18 @@ //! Scene physics module. -use crate::scene::dim2::joint::JointParams; use crate::{ - core::algebra::Vector2, - core::variable::VariableFlags, core::{ - algebra::{Isometry2, Matrix4, Point2, Translation2, UnitComplex, UnitQuaternion, Vector3}, - algebra::{Isometry3, Point3, Rotation3, Translation3}, + algebra::{ + Isometry2, Isometry3, Matrix4, Point2, Point3, Rotation3, Translation2, Translation3, + UnitComplex, UnitQuaternion, Vector2, Vector3, + }, arrayvec::ArrayVec, color::Color, inspect::{Inspect, PropertyInfo}, instant, math::Matrix4Ext, pool::Handle, + variable::VariableFlags, visitor::prelude::*, BiDirHashMap, }, @@ -20,7 +20,7 @@ use crate::{ self, collider::{self}, debug::{Line, SceneDrawingContext}, - dim2::{self, collider::ColliderShape, rigidbody::ApplyAction}, + dim2::{self, collider::ColliderShape, joint::JointParams, rigidbody::ApplyAction}, graph::{ physics::{FeatureId, IntegrationParameters, PhysicsPerformanceStatistics}, NodePool, @@ -209,22 +209,29 @@ fn convert_joint_params( JointParams::PrismaticJoint(_) => JointAxesMask::LOCKED_PRISMATIC_AXES, }; - let builder = GenericJointBuilder::new(locked_axis) + let mut joint = GenericJointBuilder::new(locked_axis) .local_frame1(local_frame1) - .local_frame2(local_frame2); + .local_frame2(local_frame2) + .build(); match params { - scene::dim2::joint::JointParams::BallJoint(v) => builder - .limits( - JointAxis::AngX, - [v.limits_angles.start, v.limits_angles.end], - ) - .build(), - scene::dim2::joint::JointParams::FixedJoint(_) => builder.build(), - scene::dim2::joint::JointParams::PrismaticJoint(v) => builder - .limits(JointAxis::X, [v.limits.start, v.limits.end]) - .build(), + scene::dim2::joint::JointParams::BallJoint(v) => { + if v.limits_enabled { + joint.set_limits( + JointAxis::AngX, + [v.limits_angles.start, v.limits_angles.end], + ); + } + } + scene::dim2::joint::JointParams::FixedJoint(_) => {} + scene::dim2::joint::JointParams::PrismaticJoint(v) => { + if v.limits_enabled { + joint.set_limits(JointAxis::X, [v.limits.start, v.limits.end]); + } + } } + + joint } // Converts descriptor in a shared shape. diff --git a/src/scene/graph/physics.rs b/src/scene/graph/physics.rs index 7ab9d0e17..213c2b655 100644 --- a/src/scene/graph/physics.rs +++ b/src/scene/graph/physics.rs @@ -341,33 +341,46 @@ fn convert_joint_params( JointParams::RevoluteJoint(_) => JointAxesMask::LOCKED_REVOLUTE_AXES, }; - let builder = GenericJointBuilder::new(locked_axis) + let mut joint = GenericJointBuilder::new(locked_axis) .local_frame1(local_frame1) - .local_frame2(local_frame2); + .local_frame2(local_frame2) + .build(); match params { - scene::joint::JointParams::BallJoint(v) => builder - .limits( - JointAxis::AngX, - [v.limits_angles.start, v.limits_angles.end], - ) - .limits( - JointAxis::AngY, - [v.limits_angles.start, v.limits_angles.end], - ) - .limits( - JointAxis::AngZ, - [v.limits_angles.start, v.limits_angles.end], - ) - .build(), - scene::joint::JointParams::FixedJoint(_) => builder.build(), - scene::joint::JointParams::PrismaticJoint(v) => builder - .limits(JointAxis::X, [v.limits.start, v.limits.end]) - .build(), - scene::joint::JointParams::RevoluteJoint(v) => builder - .limits(JointAxis::AngX, [v.limits.start, v.limits.end]) - .build(), + scene::joint::JointParams::BallJoint(v) => { + if v.x_limits_enabled { + joint.set_limits( + JointAxis::AngX, + [v.x_limits_angles.start, v.x_limits_angles.end], + ); + } + if v.y_limits_enabled { + joint.set_limits( + JointAxis::AngY, + [v.y_limits_angles.start, v.y_limits_angles.end], + ); + } + if v.z_limits_enabled { + joint.set_limits( + JointAxis::AngZ, + [v.z_limits_angles.start, v.z_limits_angles.end], + ); + } + } + scene::joint::JointParams::FixedJoint(_) => {} + scene::joint::JointParams::PrismaticJoint(v) => { + if v.limits_enabled { + joint.set_limits(JointAxis::X, [v.limits.start, v.limits.end]); + } + } + scene::joint::JointParams::RevoluteJoint(v) => { + if v.limits_enabled { + joint.set_limits(JointAxis::AngX, [v.limits.start, v.limits.end]); + } + } } + + joint } /// Creates new trimesh collider shape from given mesh node. It also bakes scale into diff --git a/src/scene/joint.rs b/src/scene/joint.rs index 61616d964..087e851db 100644 --- a/src/scene/joint.rs +++ b/src/scene/joint.rs @@ -13,18 +13,16 @@ use crate::{ impl_directly_inheritable_entity_trait, scene::{ base::{Base, BaseBuilder}, - graph::map::NodeHandleMap, - graph::Graph, + graph::{map::NodeHandleMap, Graph}, node::{Node, NodeTrait, SyncContext, TypeUuidProvider}, DirectlyInheritableEntity, }, utils::log::Log, }; use rapier3d::dynamics::ImpulseJointHandle; -use std::ops::Range; use std::{ cell::Cell, - ops::{Deref, DerefMut}, + ops::{Deref, DerefMut, Range}, }; /// Ball joint locks any translational moves between two objects on the axis between objects, but @@ -32,18 +30,46 @@ use std::{ /// pendulum, etc. #[derive(Clone, Debug, Visit, PartialEq, Inspect)] pub struct BallJoint { - /// The maximum angle allowed between the two limit axes in world-space. - #[inspect( - description = "The maximum angle allowed between the two limit axes in world-space." - )] + /// Whether X angular limits are enabled or not. Default is `false` + #[inspect(description = "Whether X angular limits are enabled or not.")] #[visit(optional)] // Backward compatibility - pub limits_angles: Range, + pub x_limits_enabled: bool, + + /// Allowed angle range around local X axis of the joint (in radians). + #[inspect(description = "Allowed angle range around local X axis of the joint (in radians).")] + #[visit(optional)] // Backward compatibility + pub x_limits_angles: Range, + + /// Whether Y angular limits are enabled or not. Default is `false` + #[inspect(description = "Whether Y angular limits are enabled or not.")] + #[visit(optional)] // Backward compatibility + pub y_limits_enabled: bool, + + /// Allowed angle range around local Y axis of the joint (in radians). + #[inspect(description = "Allowed angle range around local Y axis of the joint (in radians).")] + #[visit(optional)] // Backward compatibility + pub y_limits_angles: Range, + + /// Whether Z angular limits are enabled or not. Default is `false` + #[inspect(description = "Whether Z angular limits are enabled or not.")] + #[visit(optional)] // Backward compatibility + pub z_limits_enabled: bool, + + /// Allowed angle range around local Z axis of the joint (in radians). + #[inspect(description = "Allowed angle range around local Z axis of the joint (in radians).")] + #[visit(optional)] // Backward compatibility + pub z_limits_angles: Range, } impl Default for BallJoint { fn default() -> Self { Self { - limits_angles: -std::f32::consts::PI..std::f32::consts::PI, + x_limits_enabled: false, + x_limits_angles: -std::f32::consts::PI..std::f32::consts::PI, + y_limits_enabled: false, + y_limits_angles: -std::f32::consts::PI..std::f32::consts::PI, + z_limits_enabled: false, + z_limits_angles: -std::f32::consts::PI..std::f32::consts::PI, } } } @@ -57,9 +83,14 @@ pub struct FixedJoint; /// translations along one axis. The real world example is a sliders that used to support drawers. #[derive(Clone, Debug, Visit, PartialEq, Inspect)] pub struct PrismaticJoint { - /// The min an max relative position of the attached bodies along this joint's axis. + /// Whether linear limits along local joint X axis are enabled or not. Default is `false` + #[inspect(description = "Whether linear limits along local joint X axis are enabled or not.")] + #[visit(optional)] // Backward compatibility + pub limits_enabled: bool, + + /// The min an max relative position of the attached bodies along local X axis of the joint. #[inspect( - description = "The min an max relative position of the attached bodies along this joint's axis." + description = "The min an max relative position of the attached bodies along local X axis of the joint." )] #[visit(optional)] // Backward compatibility pub limits: Range, @@ -68,6 +99,7 @@ pub struct PrismaticJoint { impl Default for PrismaticJoint { fn default() -> Self { Self { + limits_enabled: false, limits: -std::f32::consts::PI..std::f32::consts::PI, } } @@ -78,17 +110,23 @@ impl Default for PrismaticJoint { /// hinge. #[derive(Clone, Debug, Visit, PartialEq, Inspect)] pub struct RevoluteJoint { - /// The min and max relative position of the attached bodies along this joint's axis. + /// Whether angular limits around local X axis of the joint are enabled or not. Default is `false` #[inspect( - description = "The min and max relative position of the attached bodies along this joint's axis." + description = "Whether angular limits around local X axis of the joint are enabled or not." )] #[visit(optional)] // Backward compatibility + pub limits_enabled: bool, + + /// Allowed angle range around local X axis of the joint (in radians). + #[inspect(description = "Allowed angle range around local X axis of the joint (in radians).")] + #[visit(optional)] // Backward compatibility pub limits: Range, } impl Default for RevoluteJoint { fn default() -> Self { Self { + limits_enabled: false, limits: -std::f32::consts::PI..std::f32::consts::PI, } }