Last active
March 5, 2023 13:18
-
-
Save VictorHHT/32fc5a9fa5a225a07314eaaca4a25204 to your computer and use it in GitHub Desktop.
A tool designed to view models by manipulating the camera instead of the model itself, effectively view the model in every possible angle without the quirkiness in rotating the model. Having additional features like changing view distance, panning via either mouse or keyboard. Smooth has been added to all features for this tool to improve user e…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEditor; | |
public class VTCameraRotator : MonoBehaviour | |
{ | |
public enum PanMethods { Mouse, Keyboard }; | |
// The target of the camera rotate sphere | |
public Camera sceneCamera; | |
// Target of the camera | |
public Transform target; | |
public PanMethods panMethod; | |
public bool m_CanRotate = true; | |
[Range(5f, 15f)] | |
[Tooltip("How sensitive the mouse drag to camera rotation")] | |
public float mouseRotateSpeed = 5f; | |
[Range(0.1f, 0.5f)] | |
public float mousePanSpeed = 0.25f; | |
[Range(10f, 50f)] | |
public float keyboardPanSpeed = 20f; | |
[Range(1f, 5f)] | |
public float distanceChangeSpeed = 1f; | |
[Range(0.1f, 0.5f)] | |
public float rotateSmoothValue = 0.3f; | |
[Range(0.1f, 0.3f)] | |
public float distanceChangeSmoothValue = 0.12f; | |
[Range(0.1f, 0.3f)] | |
public float panSmoothValue = 0.12f; | |
public KeyCode leftPanKeyCode = KeyCode.A; | |
public KeyCode rightPanKeyCode = KeyCode.D; | |
public KeyCode upPanKeyCode = KeyCode.W; | |
public KeyCode downPanKeyCode = KeyCode.S; | |
// Clamp Value | |
private readonly float m_MinXRotAngle = -85; //min angle around x axis | |
private readonly float m_MaxXRotAngle = 85; // max angle around x axis | |
// Mouse rotation related | |
private float m_RotAroundX; | |
private float m_RotAroundY; | |
// Mouse Scroll | |
private float m_TargetCameraDistance; | |
private float m_CurrentCameraDistance; | |
private float m_DefaultCameraDistance; | |
private float m_DummyDampFloatVelocity = 0; | |
private float m_MinCameraDistance = 1.5f; | |
private float m_MaxCameraDistance = 15; | |
private Vector3 m_DistanceVec; | |
private Vector3 m_MousePosBeforePanning; | |
private Vector3 m_RightBeforePannining; | |
private Vector3 m_UpBeforePanning; | |
private Vector3 m_CurrentPanDelta; | |
private Vector3 m_TargetPanDelta; | |
private Vector3 m_DummyDampVector3Velocity; | |
private Quaternion m_CurrentRot; | |
private Quaternion m_TargetRot; | |
void Awake() | |
{ | |
if (sceneCamera == null) | |
{ | |
sceneCamera = Camera.main; | |
} | |
} | |
// Start is called before the first frame update | |
void Start() | |
{ | |
m_DefaultCameraDistance = Vector3.Distance(sceneCamera.transform.position, target.position); | |
m_TargetCameraDistance = m_DefaultCameraDistance; | |
m_CurrentCameraDistance = m_DefaultCameraDistance; | |
// negative because default camera z value is negative | |
m_DistanceVec = new Vector3(0, 0, -m_TargetCameraDistance); | |
// Initialize camera position | |
sceneCamera.transform.position = target.position + m_DistanceVec; | |
// Initial view angle | |
m_RotAroundX = 40; | |
m_RotAroundY = 40; | |
} | |
// Update is called once per frame | |
void Update() | |
{ | |
if (!m_CanRotate) | |
{ | |
return; | |
} | |
m_DistanceVec = new Vector3(0, 0, -m_CurrentCameraDistance); | |
EditorCameraInput(); | |
HandlePanning(); | |
} | |
private void LateUpdate() | |
{ | |
RotateCamera(); | |
SetCameraDistance(); | |
} | |
public void ResetView() | |
{ | |
m_RotAroundX = 40; | |
m_RotAroundY = 40; | |
ResetPan(); | |
ResetDistance(); | |
} | |
public void ResetPan() | |
{ | |
m_TargetPanDelta = Vector3.zero; | |
} | |
public void ResetDistance() | |
{ | |
m_TargetCameraDistance = m_DefaultCameraDistance; | |
} | |
public void FrontView() | |
{ | |
m_RotAroundX = 0; | |
m_RotAroundY = 0; | |
ResetPan(); | |
} | |
//May be the problem with Euler angles | |
public void TopView() | |
{ | |
m_RotAroundX = 85; | |
m_RotAroundY = 0; | |
ResetPan(); | |
} | |
public void LeftView() | |
{ | |
m_RotAroundY = 85; | |
m_RotAroundX = 0; | |
ResetPan(); | |
} | |
private void EditorCameraInput() | |
{ | |
// Camera Rotation | |
if (Input.GetMouseButton(0)) | |
{ | |
m_RotAroundX += Input.GetAxis("Mouse Y") * mouseRotateSpeed * -1; // around X | |
m_RotAroundY += Input.GetAxis("Mouse X") * mouseRotateSpeed; | |
// Clamp rotX | |
if (m_RotAroundX < m_MinXRotAngle) | |
{ | |
m_RotAroundX = m_MinXRotAngle; | |
} | |
else if (m_RotAroundX > m_MaxXRotAngle) | |
{ | |
m_RotAroundX = m_MaxXRotAngle; | |
} | |
} | |
if (panMethod == PanMethods.Mouse) | |
{ | |
if (Input.GetMouseButtonDown(2)) | |
{ | |
m_RightBeforePannining = transform.right; | |
m_UpBeforePanning = transform.up; | |
m_MousePosBeforePanning = Input.mousePosition; | |
} | |
if (Input.GetMouseButton(2)) | |
{ | |
Vector2 mouseDelta = Input.mousePosition - m_MousePosBeforePanning; | |
m_TargetPanDelta += m_RightBeforePannining * mouseDelta.x * mousePanSpeed * Time.deltaTime; | |
m_TargetPanDelta += m_UpBeforePanning * mouseDelta.y * mousePanSpeed * Time.deltaTime; | |
} | |
if (Input.GetMouseButtonUp(2)) | |
{ | |
m_MousePosBeforePanning = Vector2.zero; | |
} | |
} | |
else | |
{ | |
if (Input.GetKeyDown(leftPanKeyCode) || Input.GetKeyDown(rightPanKeyCode)) | |
{ | |
m_RightBeforePannining = transform.right; | |
} | |
if (Input.GetKeyDown(upPanKeyCode) || Input.GetKeyDown(downPanKeyCode)) | |
{ | |
m_UpBeforePanning = transform.up; | |
} | |
if (!(Input.GetKey(leftPanKeyCode) && Input.GetKey(rightPanKeyCode))) | |
{ | |
if (Input.GetKey(leftPanKeyCode)) | |
{ | |
m_TargetPanDelta -= m_RightBeforePannining * keyboardPanSpeed * Time.deltaTime; | |
} | |
if (Input.GetKey(rightPanKeyCode)) | |
{ | |
m_TargetPanDelta += m_RightBeforePannining * keyboardPanSpeed * Time.deltaTime; | |
} | |
} | |
if (!(Input.GetKey(downPanKeyCode) && Input.GetKey(upPanKeyCode))) | |
{ | |
if (Input.GetKey(downPanKeyCode)) | |
{ | |
m_TargetPanDelta -= m_UpBeforePanning * keyboardPanSpeed * Time.deltaTime; | |
} | |
if (Input.GetKey(upPanKeyCode)) | |
{ | |
m_TargetPanDelta += m_UpBeforePanning * keyboardPanSpeed * Time.deltaTime; | |
} | |
} | |
} | |
if (Input.mouseScrollDelta.magnitude > 0) | |
{ | |
m_TargetCameraDistance += Input.mouseScrollDelta.y * distanceChangeSpeed * -1; | |
} | |
} | |
private void RotateCamera() | |
{ | |
Vector3 targetRot = new Vector3(m_RotAroundX, m_RotAroundY, 0); | |
m_TargetRot = Quaternion.Euler(targetRot); | |
//Rotate Camera | |
m_CurrentRot = Quaternion.Slerp(m_CurrentRot, m_TargetRot, Time.smoothDeltaTime * rotateSmoothValue * 50); | |
sceneCamera.transform.position = target.position + m_CurrentRot * m_DistanceVec; | |
sceneCamera.transform.LookAt(target.position); | |
sceneCamera.transform.position += m_CurrentPanDelta; | |
} | |
void SetCameraDistance() | |
{ | |
if (m_TargetCameraDistance >= m_MaxCameraDistance) | |
{ | |
m_TargetCameraDistance = m_MaxCameraDistance; | |
} | |
else if (m_TargetCameraDistance <= m_MinCameraDistance) | |
{ | |
m_TargetCameraDistance = m_MinCameraDistance; | |
} | |
m_CurrentCameraDistance = Mathf.SmoothDamp(m_CurrentCameraDistance, m_TargetCameraDistance, ref m_DummyDampFloatVelocity, distanceChangeSmoothValue); | |
} | |
void HandlePanning() | |
{ | |
m_CurrentPanDelta = Vector3.SmoothDamp(m_CurrentPanDelta, m_TargetPanDelta, ref m_DummyDampVector3Velocity, panSmoothValue); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment