//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
using System;
using bs;
namespace bs.Editor
{
/** @addtogroup Gizmos
* @{
*/
///
/// Handles drawing of gizmos for all the types of component.
///
internal class JointGizmos
{
///
/// Returns the anchor position for the specified joint body. Anchor represents the world position of the rigidbody
/// added to the offset provided by the joint.
///
/// Joint from which to retrieve the body.
/// Body to retrieve the anchor for.
/// Anchor position in world space.
private static Vector3 GetAnchor(Joint joint, JointBody body)
{
Rigidbody rigidbody = joint.GetBody(body);
Vector3 anchor = joint.GetPosition(body);
if (rigidbody != null)
{
Quaternion worldRot = rigidbody.SceneObject.Rotation;
anchor = worldRot.Rotate(anchor) + rigidbody.SceneObject.Position;
}
else
{
Quaternion worldRot = joint.SceneObject.Rotation;
anchor = worldRot.Rotate(anchor) + joint.SceneObject.Position;
}
return anchor;
}
///
/// Method called by the runtime when joints are meant to be drawn.
///
/// Joint to draw gizmos for.
[DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
private static void DrawFixedJoint(FixedJoint joint)
{
Vector3 target = GetAnchor(joint, JointBody.Target);
Vector3 anchor = GetAnchor(joint, JointBody.Anchor);
Gizmos.Color = Color.White;
Gizmos.DrawSphere(target, 0.05f);
Gizmos.DrawSphere(anchor, 0.05f);
Gizmos.Color = Color.Green;
Gizmos.DrawLine(target, anchor);
}
///
/// Method called by the runtime when joints are meant to be drawn.
///
/// Joint to draw gizmos for.
[DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
private static void DrawDistanceJoint(DistanceJoint joint)
{
Vector3 anchorA = GetAnchor(joint, JointBody.Target);
Vector3 anchorB = GetAnchor(joint, JointBody.Anchor);
Gizmos.Color = Color.White;
Gizmos.DrawSphere(anchorA, 0.05f);
Gizmos.DrawSphere(anchorB, 0.05f);
Gizmos.Color = Color.Red;
Vector3 diff = anchorB - anchorA;
float length = diff.Length;
Vector3 normal = diff.Normalized;
float min = 0.0f;
float max = length;
if (joint.HasFlag(DistanceJointFlag.MinDistance))
{
min = MathEx.Max(0.0f, joint.MinDistance);
if (joint.HasFlag(DistanceJointFlag.MaxDistance))
min = MathEx.Min(min, MathEx.Min(10000.0f, joint.MaxDistance));
Gizmos.DrawLine(anchorA, anchorA + normal * min);
}
if (joint.HasFlag(DistanceJointFlag.MaxDistance))
{
max = MathEx.Min(10000.0f, joint.MaxDistance);
if (joint.HasFlag(DistanceJointFlag.MinDistance))
max = MathEx.Max(max, min);
if (length > max)
Gizmos.DrawLine(anchorA + normal * max, anchorA + normal * length);
}
Gizmos.Color = Color.Green;
Gizmos.DrawLine(anchorA + normal * min, anchorA + normal * MathEx.Min(max, length));
}
///
/// Method called by the runtime when joints are meant to be drawn.
///
/// Joint to draw gizmos for.
[DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
private static void DrawSliderJoint(SliderJoint joint)
{
Vector3 anchor = GetAnchor(joint, JointBody.Anchor);
Vector3 target = GetAnchor(joint, JointBody.Target);
Vector3 normal = -joint.SceneObject.Right;
if (joint.HasFlag(SliderJointFlag.Limit))
{
LimitLinearRange limit = joint.Limit;
float max = MathEx.Min(10000.0f, limit.upper);
float min = MathEx.Clamp(limit.lower, 0.0f, max);
max = MathEx.Max(max, min);
Gizmos.Color = Color.Red;
Gizmos.DrawLine(anchor, anchor + normal*min);
Gizmos.Color = Color.Green;
Gizmos.DrawLine(anchor + normal*min, anchor + normal*max);
}
else
{
Gizmos.Color = Color.Green;
float length = 100.0f;
Gizmos.DrawLine(anchor, anchor + normal * length);
}
Gizmos.Color = Color.Yellow;
Gizmos.DrawSphere(target, 0.05f);
}
///
/// Method called by the runtime when joints are meant to be drawn.
///
/// Joint to draw gizmos for.
[DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
private static void DrawSphericalJoint(SphericalJoint joint)
{
Vector3 target = GetAnchor(joint, JointBody.Target);
Vector3 anchor = GetAnchor(joint, JointBody.Anchor);
Vector3 center = target;
Rigidbody rigidbody = joint.GetBody(JointBody.Target);
if (rigidbody != null)
center = rigidbody.SceneObject.Position;
Gizmos.Color = Color.White;
Gizmos.DrawSphere(center, 0.05f);
Gizmos.Color = Color.Yellow;
Gizmos.DrawSphere(target, 0.05f);
Gizmos.DrawSphere(anchor, 0.05f);
Gizmos.Color = Color.Green;
Gizmos.DrawLine(target, center);
Gizmos.Color = Color.Green;
if (joint.HasFlag(SphericalJointFlag.Limit))
{
LimitConeRange limit = joint.Limit;
Radian zAngle = MathEx.Min(new Degree(360), limit.zLimitAngle * 2.0f);
Radian yAngle = MathEx.Min(new Degree(360), limit.yLimitAngle * 2.0f);
Gizmos.Transform = joint.SceneObject.WorldTransform;
Gizmos.DrawWireArc(Vector3.Zero, Vector3.ZAxis, 0.25f, zAngle * -0.5f + new Degree(90), zAngle);
Gizmos.DrawWireArc(Vector3.Zero, Vector3.YAxis, 0.25f, yAngle * -0.5f + new Degree(90), yAngle);
Gizmos.Color = Color.Red;
Radian remainingZAngle = new Degree(360) - zAngle;
Radian remainingYAngle = new Degree(360) - yAngle;
Gizmos.DrawWireArc(Vector3.Zero, Vector3.ZAxis, 0.25f, zAngle * 0.5f + new Degree(90), remainingZAngle);
Gizmos.DrawWireArc(Vector3.Zero, Vector3.YAxis, 0.25f, yAngle * 0.5f + new Degree(90), remainingYAngle);
}
else
{
Gizmos.Color = Color.Green;
Gizmos.Transform = joint.SceneObject.WorldTransform;
Gizmos.DrawWireDisc(Vector3.Zero, Vector3.ZAxis, 0.25f);
Gizmos.DrawWireDisc(Vector3.Zero, Vector3.YAxis, 0.25f);
}
}
///
/// Method called by the runtime when joints are meant to be drawn.
///
/// Joint to draw gizmos for.
[DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
private static void DrawHingeJoint(HingeJoint joint)
{
Vector3 target = GetAnchor(joint, JointBody.Target);
Vector3 anchor = GetAnchor(joint, JointBody.Anchor);
Vector3 center = target;
Rigidbody rigidbody = joint.GetBody(JointBody.Target);
if (rigidbody != null)
center = rigidbody.SceneObject.Position;
Gizmos.Color = Color.White;
Gizmos.DrawSphere(center, 0.05f);
Gizmos.Color = Color.Yellow;
Gizmos.DrawSphere(target, 0.05f);
Gizmos.DrawSphere(anchor, 0.05f);
Gizmos.Color = Color.Green;
Gizmos.DrawLine(target, center);
const float radius = 0.25f;
const float height = 0.5f;
if (joint.HasFlag(HingeJointFlag.Limit))
{
Gizmos.Transform = joint.SceneObject.WorldTransform;
LimitAngularRange limit = joint.Limit;
Action drawLimitedArc = x =>
{
Degree lower = MathEx.WrapAngle(limit.lower);
Degree upper = MathEx.WrapAngle(limit.upper);
lower = MathEx.Min(lower, upper);
upper = MathEx.Max(upper, lower);
// Arc zero to lower limit
Gizmos.Color = Color.Red;
Gizmos.DrawWireArc(Vector3.XAxis * x, Vector3.XAxis, radius, new Degree(0.0f), lower);
// Arc lower to upper limit
Degree validRange = upper - lower;
Gizmos.Color = Color.Green;
Gizmos.DrawWireArc(Vector3.XAxis * x, Vector3.XAxis, radius, lower, validRange);
// Arc upper to full circle
Degree remainingRange = new Degree(360) - upper;
Gizmos.Color = Color.Red;
Gizmos.DrawWireArc(Vector3.XAxis * x, Vector3.XAxis, radius, upper, remainingRange);
};
drawLimitedArc(-height);
drawLimitedArc(height);
}
else
{
Gizmos.Color = Color.Green;
Gizmos.Transform = joint.SceneObject.WorldTransform;
Gizmos.DrawWireDisc(Vector3.XAxis * -height, Vector3.XAxis, radius);
Gizmos.DrawWireDisc(Vector3.XAxis * height, Vector3.XAxis, radius);
}
Vector3[] lineStartPoints = new Vector3[4];
lineStartPoints[0] = new Vector3(-height, radius, 0);
lineStartPoints[1] = new Vector3(-height, -radius, 0);
lineStartPoints[2] = new Vector3(-height, 0, radius);
lineStartPoints[3] = new Vector3(-height, 0, -radius);
Vector3[] lineEndPoints = new Vector3[4];
lineEndPoints[0] = new Vector3(height, radius, 0);
lineEndPoints[1] = new Vector3(height, -radius, 0);
lineEndPoints[2] = new Vector3(height, 0, radius);
lineEndPoints[3] = new Vector3(height, 0, -radius);
Gizmos.Color = Color.Green;
for (int i = 0; i < 4; i++)
Gizmos.DrawLine(lineStartPoints[i], lineEndPoints[i]);
}
///
/// Method called by the runtime when joints are meant to be drawn.
///
/// Joint to draw gizmos for.
[DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
private static void DrawD6Joint(D6Joint joint)
{
Vector3 anchorA = GetAnchor(joint, JointBody.Target);
Vector3 anchorB = GetAnchor(joint, JointBody.Anchor);
Gizmos.Color = Color.White;
Gizmos.DrawSphere(anchorA, 0.05f);
Gizmos.DrawSphere(anchorB, 0.05f);
}
}
/** @} */
}