forked from BilalY/Rasagar
174 lines
8.1 KiB
C#
174 lines
8.1 KiB
C#
|
using UnityEngine;
|
||
|
using UnityEditor;
|
||
|
|
||
|
namespace Cinemachine.Editor
|
||
|
{
|
||
|
[CustomEditor(typeof(Cinemachine3rdPersonFollow))]
|
||
|
[CanEditMultipleObjects]
|
||
|
internal class Cinemachine3rdPersonFollowEditor : BaseEditor<Cinemachine3rdPersonFollow>
|
||
|
{
|
||
|
[DrawGizmo(GizmoType.Active | GizmoType.Selected, typeof(Cinemachine3rdPersonFollow))]
|
||
|
static void Draw3rdPersonGizmos(Cinemachine3rdPersonFollow target, GizmoType selectionType)
|
||
|
{
|
||
|
if (target.IsValid)
|
||
|
{
|
||
|
var isLive = CinemachineCore.Instance.IsLive(target.VirtualCamera);
|
||
|
Color originalGizmoColour = Gizmos.color;
|
||
|
Gizmos.color = isLive
|
||
|
? CinemachineSettings.CinemachineCoreSettings.ActiveGizmoColour
|
||
|
: CinemachineSettings.CinemachineCoreSettings.InactiveGizmoColour;
|
||
|
|
||
|
target.GetRigPositions(out Vector3 root, out Vector3 shoulder, out Vector3 hand);
|
||
|
Gizmos.DrawLine(root, shoulder);
|
||
|
Gizmos.DrawLine(shoulder, hand);
|
||
|
Gizmos.DrawSphere(root, 0.02f);
|
||
|
Gizmos.DrawSphere(shoulder, 0.02f);
|
||
|
#if CINEMACHINE_PHYSICS
|
||
|
Gizmos.DrawSphere(hand, target.CameraRadius);
|
||
|
|
||
|
if (isLive)
|
||
|
Gizmos.color = CinemachineSettings.CinemachineCoreSettings.BoundaryObjectGizmoColour;
|
||
|
|
||
|
Gizmos.DrawSphere(target.VirtualCamera.State.RawPosition, target.CameraRadius);
|
||
|
#endif
|
||
|
|
||
|
Gizmos.color = originalGizmoColour;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void OnInspectorGUI()
|
||
|
{
|
||
|
BeginInspector();
|
||
|
bool needWarning = false;
|
||
|
for (int i = 0; !needWarning && i < targets.Length; ++i)
|
||
|
needWarning = (targets[i] as Cinemachine3rdPersonFollow).FollowTarget == null;
|
||
|
if (needWarning)
|
||
|
EditorGUILayout.HelpBox(
|
||
|
"3rd Person Follow requires a Follow Target. Change Body to Do Nothing if you don't want a Follow target.",
|
||
|
MessageType.Warning);
|
||
|
DrawRemainingPropertiesInInspector();
|
||
|
}
|
||
|
|
||
|
#if UNITY_2021_2_OR_NEWER
|
||
|
protected virtual void OnEnable()
|
||
|
{
|
||
|
CinemachineSceneToolUtility.RegisterTool(typeof(FollowOffsetTool));
|
||
|
}
|
||
|
|
||
|
protected virtual void OnDisable()
|
||
|
{
|
||
|
CinemachineSceneToolUtility.UnregisterTool(typeof(FollowOffsetTool));
|
||
|
}
|
||
|
|
||
|
void OnSceneGUI()
|
||
|
{
|
||
|
DrawSceneTools();
|
||
|
}
|
||
|
|
||
|
void DrawSceneTools()
|
||
|
{
|
||
|
var thirdPerson = Target;
|
||
|
if (thirdPerson == null || !thirdPerson.IsValid)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (CinemachineSceneToolUtility.IsToolActive(typeof(FollowOffsetTool)))
|
||
|
{
|
||
|
var originalColor = Handles.color;
|
||
|
|
||
|
thirdPerson.GetRigPositions(out var followTargetPosition, out var shoulderPosition,
|
||
|
out var armPosition);
|
||
|
var followTargetRotation = thirdPerson.FollowTargetRotation;
|
||
|
var targetForward = followTargetRotation * Vector3.forward;
|
||
|
var heading = Cinemachine3rdPersonFollow.GetHeading(
|
||
|
followTargetRotation, thirdPerson.VirtualCamera.State.ReferenceUp);
|
||
|
|
||
|
EditorGUI.BeginChangeCheck();
|
||
|
// shoulder handle
|
||
|
#if UNITY_2022_2_OR_NEWER
|
||
|
var sHandleIds = Handles.PositionHandleIds.@default;
|
||
|
var newShoulderPosition = Handles.PositionHandle(sHandleIds, shoulderPosition, heading);
|
||
|
var sHandleMinId = sHandleIds.x - 1;
|
||
|
var sHandleMaxId = sHandleIds.xyz + 1;
|
||
|
#else
|
||
|
var sHandleMinId = GUIUtility.GetControlID(FocusType.Passive);
|
||
|
var newShoulderPosition = Handles.PositionHandle(shoulderPosition, heading);
|
||
|
var sHandleMaxId = GUIUtility.GetControlID(FocusType.Passive);
|
||
|
#endif
|
||
|
|
||
|
Handles.color = Handles.preselectionColor;
|
||
|
// arm handle
|
||
|
var followUp = followTargetRotation * Vector3.up;
|
||
|
var aHandleId = GUIUtility.GetControlID(FocusType.Passive);
|
||
|
var newArmPosition = Handles.Slider(aHandleId, armPosition, followUp,
|
||
|
CinemachineSceneToolHelpers.CubeHandleCapSize(armPosition), Handles.CubeHandleCap, 0.5f);
|
||
|
|
||
|
// cam distance handle
|
||
|
var camDistance = thirdPerson.CameraDistance;
|
||
|
var camPos = armPosition - targetForward * camDistance;
|
||
|
var cdHandleId = GUIUtility.GetControlID(FocusType.Passive);
|
||
|
var newCamPos = Handles.Slider(cdHandleId, camPos, targetForward,
|
||
|
CinemachineSceneToolHelpers.CubeHandleCapSize(camPos), Handles.CubeHandleCap, 0.5f);
|
||
|
if (EditorGUI.EndChangeCheck())
|
||
|
{
|
||
|
// Modify via SerializedProperty for OnValidate to get called automatically, and scene repainting too
|
||
|
var so = new SerializedObject(thirdPerson);
|
||
|
|
||
|
var shoulderOffset = so.FindProperty(() => thirdPerson.ShoulderOffset);
|
||
|
shoulderOffset.vector3Value +=
|
||
|
CinemachineSceneToolHelpers.PositionHandleDelta(heading, newShoulderPosition, shoulderPosition);
|
||
|
var verticalArmLength = so.FindProperty(() => thirdPerson.VerticalArmLength);
|
||
|
verticalArmLength.floatValue +=
|
||
|
CinemachineSceneToolHelpers.SliderHandleDelta(newArmPosition, armPosition, followUp);
|
||
|
var cameraDistance = so.FindProperty(() => thirdPerson.CameraDistance);
|
||
|
cameraDistance.floatValue -=
|
||
|
CinemachineSceneToolHelpers.SliderHandleDelta(newCamPos, camPos, targetForward);
|
||
|
|
||
|
so.ApplyModifiedProperties();
|
||
|
}
|
||
|
|
||
|
var isDragged = IsHandleDragged(sHandleMinId, sHandleMaxId, shoulderPosition, "Shoulder Offset "
|
||
|
+ thirdPerson.ShoulderOffset.ToString("F1"), followTargetPosition, shoulderPosition);
|
||
|
isDragged |= IsHandleDragged(aHandleId, aHandleId, armPosition, "Vertical Arm Length ("
|
||
|
+ thirdPerson.VerticalArmLength.ToString("F1") + ")", shoulderPosition, armPosition);
|
||
|
isDragged |= IsHandleDragged(cdHandleId, cdHandleId, camPos, "Camera Distance ("
|
||
|
+ camDistance.ToString("F1") + ")", armPosition, camPos);
|
||
|
|
||
|
CinemachineSceneToolHelpers.SoloOnDrag(isDragged, thirdPerson.VirtualCamera, sHandleMaxId);
|
||
|
|
||
|
Handles.color = originalColor;
|
||
|
}
|
||
|
|
||
|
// local function that draws label and guide lines, and returns true if a handle has been dragged
|
||
|
static bool IsHandleDragged
|
||
|
(int handleMinId, int handleMaxId, Vector3 labelPos, string text, Vector3 lineStart, Vector3 lineEnd)
|
||
|
{
|
||
|
bool handleIsDragged;
|
||
|
bool handleIsDraggedOrHovered;
|
||
|
if (handleMinId == handleMaxId) {
|
||
|
handleIsDragged = GUIUtility.hotControl == handleMinId;
|
||
|
handleIsDraggedOrHovered = handleIsDragged || HandleUtility.nearestControl == handleMinId;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
handleIsDragged = handleMinId < GUIUtility.hotControl && GUIUtility.hotControl < handleMaxId;
|
||
|
handleIsDraggedOrHovered = handleIsDragged ||
|
||
|
(handleMinId < HandleUtility.nearestControl && HandleUtility.nearestControl < handleMaxId);
|
||
|
}
|
||
|
|
||
|
if (handleIsDraggedOrHovered)
|
||
|
CinemachineSceneToolHelpers.DrawLabel(labelPos, text);
|
||
|
|
||
|
Handles.color = handleIsDraggedOrHovered ?
|
||
|
Handles.selectedColor : CinemachineSceneToolHelpers.HelperLineDefaultColor;
|
||
|
Handles.DrawLine(lineStart, lineEnd, CinemachineSceneToolHelpers.LineThickness);
|
||
|
|
||
|
return handleIsDragged;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|