//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
namespace BansheeEngine
{
/** @addtogroup Physics
* @{
*/
///
/// Represents the most customizable type of joint. This joint type can be used to create all other built-in joint
/// types, and to design your own custom ones, but is less intuitive to use. Allows a specification of a linear
/// constraint (for example for slider), twist constraint(rotating around X) and swing constraint(rotating around Y and
/// Z). It also allows you to constrain limits to only specific axes or completely lock specific axes.
///
public sealed class D6Joint : Joint
{
[SerializeField]
private SerializableData data = new SerializableData();
///
/// Returns the current rotation of the joint around the X axis.
///
public Radian Twist
{
get
{
if (Native != null)
return Native.Twist;
return new Radian(0.0f);
}
}
///
/// Returns the current rotation of the joint around the Y axis.
///
public Radian SwingY
{
get
{
if (Native != null)
return Native.SwingY;
return new Radian(0.0f);
}
}
///
/// Returns the current rotation of the joint around the Z axis.
///
public Radian SwingZ
{
get
{
if (Native != null)
return Native.SwingZ;
return new Radian(0.0f);
}
}
///
/// Linear limit used for constraining translation degrees of freedom.
///
public LimitLinear LimitLinear
{
get { return data.@internal.linearLimit; }
set
{
if (data.@internal.linearLimit == value)
return;
data.@internal.linearLimit = value;
if (Native != null)
Native.LimitLinear = value;
}
}
///
/// Angular limit used for constraining the twist (rotation around X) degree of freedom.
///
public LimitAngularRange LimitTwist
{
get { return data.@internal.twistLimit; }
set
{
if (data.@internal.twistLimit == value)
return;
data.@internal.twistLimit = value;
if (Native != null)
Native.LimitTwist = value;
}
}
///
/// Cone limit used for constraining the swing (rotation around Y and Z) degree of freedom.
///
public LimitConeRange LimitSwing
{
get { return data.@internal.swingLimit; }
set
{
if (data.@internal.swingLimit == value)
return;
data.@internal.swingLimit = value;
if (Native != null)
Native.LimitSwing = value;
}
}
///
/// Determines the drive's target position relative to the joint's first body. This is the position the drive will
/// attempt to reach if enabled.
///
public Vector3 DrivePosition
{
get { return data.@internal.drivePosition; }
set
{
if (data.@internal.drivePosition == value)
return;
data.@internal.drivePosition = value;
if (Native != null)
Native.DrivePosition = value;
}
}
///
/// Determines the drive's target orientation relative to the joint's first body. This is the orientation the drive
/// will attempt to reach if enabled.
///
public Quaternion DriveRotation
{
get { return data.@internal.driveRotation; }
set
{
if (data.@internal.driveRotation == value)
return;
data.@internal.driveRotation = value;
if (Native != null)
Native.DriveRotation = value;
}
}
///
/// Determines the drive's target linear velocity. This is the velocity the drive will attempt to reach if enabled.
///
public Vector3 DriveLinearVelocity
{
get { return data.@internal.driveLinearVelocity; }
set
{
if (data.@internal.driveLinearVelocity == value)
return;
data.@internal.driveLinearVelocity = value;
if (Native != null)
Native.DriveLinearVelocity = value;
}
}
///
/// Determines the drive's target angular velocity. This is the velocity the drive will attempt to reach if enabled.
///
public Vector3 DriveAngularVelocity
{
get { return data.@internal.driveAngularVelocity; }
set
{
if (data.@internal.driveAngularVelocity == value)
return;
data.@internal.driveAngularVelocity = value;
if (Native != null)
Native.DriveAngularVelocity = value;
}
}
///
/// Returns the type of motion constrain for the specified axis.
///
/// Axis to retrieve the motion constrain for.
/// Motion constrain type for the axis.
public D6JointMotion GetMotion(D6JointAxis axis)
{
return data.@internal.motion[(int) axis];
}
///
/// Allows you to constrain motion of the specified axis. Be aware that when setting drives for a specific axis
/// you must also take care not to constrain its motion in a conflicting way(for example you cannot add a drive
/// that moves the joint on X axis, and then lock the X axis).
///
/// Unlocking translations degrees of freedom allows the bodies to move along the subset of the unlocked axes.
/// (for example unlocking just one translational axis is the equivalent of a slider joint.)
///
/// Angular degrees of freedom are partitioned as twist(around X axis) and swing(around Y and Z axes). Different
/// effects can be achieves by unlocking their various combinations:
/// - If a single degree of angular freedom is unlocked it should be the twist degree as it has extra options for
/// that case (for example for a hinge joint).
/// - If both swing degrees are unlocked but twist is locked the result is a zero-twist joint.
/// - If one swing and one twist degree of freedom are unlocked the result is a zero-swing joint (for example an
/// arm attached at the elbow)
/// - If all angular degrees of freedom are unlocked the result is the same as the spherical joint.
///
/// Axis to change the motion type for.
/// Type of motion for the axis.
public void SetMotion(D6JointAxis axis, D6JointMotion motion)
{
if (data.@internal.motion[(int)axis] == motion)
return;
data.@internal.motion[(int)axis] = motion;
if (Native != null)
Native.SetMotion(axis, motion);
}
///
/// Returns properties for the specified drive type.
///
/// Type of drive to retrieve properties for.
/// Properties for the requested drive type.
public D6JointDrive GetDrive(D6JointDriveType type)
{
return data.@internal.drives[(int) type];
}
///
/// Sets a drive that will attempt to move the specified degree(s) of freedom to the wanted position and velocity.
///
/// Type of the drive.
/// Drive properties.
public void SetDrive(D6JointDriveType type, D6JointDrive drive)
{
if (data.@internal.drives[(int)type] == drive)
return;
data.@internal.drives[(int)type] = drive;
if (Native != null)
Native.SetDrive(type, drive);
}
///
/// Returns the native joint wrapped by this component.
///
private NativeD6Joint Native
{
get { return (NativeD6Joint)native; }
}
///
internal override NativeJoint CreateNative()
{
NativeD6Joint joint = new NativeD6Joint(commonData.@internal, data.@internal);
return joint;
}
///
/// Holds all data the joint component needs to persist through serialization.
///
[SerializeObject]
internal new class SerializableData
{
public ScriptD6JointData @internal;
public SerializableData()
{
@internal.linearLimit = new LimitLinear();
@internal.twistLimit = new LimitAngularRange();
@internal.swingLimit = new LimitConeRange();
@internal.motion = new D6JointMotion[(int)D6JointAxis.Count];
@internal.drives = new D6JointDrive[(int)D6JointDriveType.Count];
@internal.drivePosition = Vector3.Zero;
@internal.driveRotation = Quaternion.Identity;
@internal.driveLinearVelocity = Vector3.Zero;
@internal.driveAngularVelocity = Vector3.Zero;
for (int i = 0; i < (int) D6JointAxis.Count; i++)
@internal.drives[i] = new D6JointDrive();
}
}
}
/** @} */
}