private void ShowSphericalLimits(JointAngularLimitHandle handle, ArticulationBody body, Matrix4x4 parentAnchorSpace) { using (new Handles.DrawingScope(parentAnchorSpace)) { handle.xMin = body.xDrive.lowerLimit; handle.xMax = body.xDrive.upperLimit; handle.yMin = body.yDrive.lowerLimit; handle.yMax = body.yDrive.upperLimit; handle.zMin = body.zDrive.lowerLimit; handle.zMax = body.zDrive.upperLimit; EditorGUI.BeginChangeCheck(); handle.radius = HandleUtility.GetHandleSize(Vector3.zero); handle.DrawHandle(true); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Changing Articulation body parent anchor rotation limits"); body.xDrive = SetDriveLimits(body.xDrive, handle.xMin, handle.xMax); body.yDrive = SetDriveLimits(body.yDrive, handle.yMin, handle.yMax); body.zDrive = SetDriveLimits(body.zDrive, handle.zMin, handle.zMax); } } }
public static void EditLimits(RigidTransform worldFromA, RigidTransform worldFromB, float3 pivotA, float3 axisA, float3 axisB, float3 perpendicularA, float3 perpendicularB, ref float minLimit, ref float maxLimit, JointAngularLimitHandle limitHandle, Object target) { // Transform to world space float3 pivotAinW = math.transform(worldFromA, pivotA); float3 axisAinW = math.rotate(worldFromA, axisA); float3 perpendicularAinW = math.rotate(worldFromA, perpendicularA); float3 axisBinW = math.rotate(worldFromA, axisB); float3 perpendicularBinW = math.rotate(worldFromB, perpendicularB); // Get rotations from joint space // JointAngularLimitHandle uses axis = (1, 0, 0) with angle = 0 at (0, 0, 1), so choose the rotations to point those in the directions of our axis and perpendicular float3x3 worldFromJointA = new float3x3(axisAinW, -math.cross(axisAinW, perpendicularAinW), perpendicularAinW); float3x3 worldFromJointB = new float3x3(axisBinW, -math.cross(axisBinW, perpendicularBinW), perpendicularBinW); float3x3 jointBFromA = math.mul(math.transpose(worldFromJointB), worldFromJointA); // Set orientation for the angular limit control float angle = CalculateTwistAngle(new quaternion(jointBFromA), 0); // index = 0 because axis is the first column in worldFromJoint quaternion limitOrientation = math.mul(quaternion.AxisAngle(axisAinW, angle), new quaternion(worldFromJointA)); Matrix4x4 handleMatrix = Matrix4x4.TRS(pivotAinW, limitOrientation, Vector3.one); float size = HandleUtility.GetHandleSize(pivotAinW) * 0.75f; limitHandle.xMin = -maxLimit; limitHandle.xMax = -minLimit; limitHandle.xMotion = ConfigurableJointMotion.Limited; limitHandle.yMotion = ConfigurableJointMotion.Locked; limitHandle.zMotion = ConfigurableJointMotion.Locked; limitHandle.yHandleColor = new Color(0, 0, 0, 0); limitHandle.zHandleColor = new Color(0, 0, 0, 0); limitHandle.radius = size; using (new Handles.DrawingScope(handleMatrix)) { // Draw the reference axis float3 z = new float3(0, 0, 1); // ArrowHandleCap() draws an arrow pointing in (0, 0, 1) Handles.ArrowHandleCap(0, float3.zero, Quaternion.FromToRotation(z, new float3(1, 0, 0)), size, Event.current.type); // Draw the limit editor handle EditorGUI.BeginChangeCheck(); limitHandle.DrawHandle(); if (EditorGUI.EndChangeCheck()) { // Record the target object before setting new limits so changes can be undone/redone Undo.RecordObject(target, "Edit joint angular limits"); minLimit = -limitHandle.xMax; maxLimit = -limitHandle.xMin; } } }