using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[System.Serializable]
public class CameraPositions
{
public Vector3 position;
public Vector2 rotation;
public float distance;
}
public class CameraOrbitController : MonoBehaviour
{
public Transform target;
public Transform defaultTarget;
public Vector3 targetOffset;
public float distance = 5.0f;
public float maxDistance = 20;
public float minDistance = .6f;
public float xSpeed = 5.0f;
public float ySpeed = 5.0f;
public int yMinLimit = -80;
public int yMaxLimit = 80;
public float zoomRate = 10.0f;
public float touchZoomRate = 10.0f;
public float panSpeed = 0.3f;
public float zoomDampening = 5.0f;
public float rotationDampening = 5.0f;
[SerializeField]
private float xDeg = 0.0f;
[SerializeField]
private float yDeg = 0.0f;
private float currentDistance;
private float desiredDistance;
private Quaternion currentRotation;
private Quaternion desiredRotation;
private Quaternion rotation;
private Vector3 position;
private Vector3 FirstPosition;
private Vector3 delta;
private Vector3 lastOffset;
public List<CameraPositions> cameraPositions;
private Touchscreen screen;
public PlatformDetector platformScript;
void Start() { Init(); }
void OnEnable() { Init(); }
bool isEnabled = true;
public void Init()
{
if (!target)
{
GameObject go = new GameObject("OrbitCamTarget");
go.transform.position = Vector3.zero+new Vector3(0,1,0);
target = go.transform;
}
distance = Vector3.Distance(transform.position, target.position);
currentDistance = distance;
desiredDistance = distance;
position = transform.position;
rotation = transform.rotation;
currentRotation = transform.rotation;
desiredRotation = transform.rotation;
xDeg = Vector3.Angle(Vector3.right, transform.right);
yDeg = Vector3.Angle(Vector3.up, transform.up);
screen = Touchscreen.current;
RestPosition();
}
public void ChangeCamPosition(int index)
{
UpdateConfig(cameraPositions[index].position, cameraPositions[index].rotation.y, cameraPositions[index].rotation.x, cameraPositions[index].distance);
}
public void RestPosition()
{
target = defaultTarget;
UpdateConfig(cameraPositions[0].position, cameraPositions[0].rotation.y, cameraPositions[0].rotation.x, cameraPositions[0].distance);
}
void LateUpdate()
{
if (!Application.isEditor && isEnabled && platformScript.isTouch)
{
List<TouchControl> touches = ActiveTouches(screen);
// Debug.Log("touches: " + touches.Count.ToString());
//ZOOM & PAN
if (touches.Count == 2)
{
TouchControl touchZero = touches[0];
TouchControl touchOne = touches[1];
//ZOOM
Vector2 touchZeroPreviousPosition = touchZero.position.ReadValue() - touchZero.delta.ReadValue();
Vector2 touchOnePreviousPosition = touchOne.position.ReadValue() - touchOne.delta.ReadValue();
float prevTouchDeltaMag = (touchZeroPreviousPosition - touchOnePreviousPosition).magnitude;
float TouchDeltaMag = (touchZero.position.ReadValue() - touchOne.position.ReadValue()).magnitude;
float deltaMagDiff = prevTouchDeltaMag - TouchDeltaMag;
desiredDistance += deltaMagDiff * Time.deltaTime * touchZoomRate * 0.0025f * Mathf.Abs(desiredDistance);
Vector2 previousPositionMiddle = (touchZeroPreviousPosition + touchOnePreviousPosition) / 2;
Vector2 currentPositionMiddle = (touchZero.position.ReadValue() + touchOne.position.ReadValue()) / 2;
Vector2 middlePositionDelta = currentPositionMiddle - previousPositionMiddle;
lastOffset = targetOffset;
float speedMulti = 0.003f * panSpeed * currentDistance;
//move targetoffset on the XZ plane according to the delta
targetOffset = lastOffset + transform.right * middlePositionDelta.x * speedMulti + transform.up * middlePositionDelta.y * speedMulti;
}
//ORBIT
if (touches.Count == 1 && touches[0].phase.ReadValue() == UnityEngine.InputSystem.TouchPhase.Moved)
{
Vector2 touchposition = touches[0].delta.ReadValue();
xDeg += touchposition.x * xSpeed * 0.03f;
yDeg -= touchposition.y * ySpeed * 0.03f;
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
}
}
desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
currentRotation = transform.rotation;
rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * rotationDampening);
transform.rotation = rotation;
#if UNITY_STANDALONE || UNITY_WEBGL || UNITY_EDITOR
if (isEnabled && !platformScript.isTouch)
{
//Mouse Rotate
if (Mouse.current.leftButton.isPressed)
{
FirstPosition = Mouse.current.delta.ReadValue();
xDeg += FirstPosition.x * xSpeed * 0.03f;
yDeg -= FirstPosition.y * ySpeed * 0.03f;
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
}
//Mouse Pan
if (Mouse.current.rightButton.isPressed)
{
delta = Mouse.current.delta.ReadValue();
targetOffset += lastOffset + transform.right * delta.x * 0.003f * panSpeed * currentDistance + transform.up * delta.y * 0.003f * panSpeed * currentDistance;
}
}
//Debug.Log(Mouse.current.scroll.magnitude);
//Mouse Zoom
if (Mouse.current.scroll.magnitude>0)
{
Vector2 scrollValue = Mouse.current.scroll.ReadValue();
Debug.Log($"Scroll value: {scrollValue}");
desiredDistance += Mouse.current.scroll.ReadValue().normalized.y * -zoomRate*Time.deltaTime;
}
#endif
desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
position = target.position - (rotation * Vector3.forward * currentDistance);
position = position - targetOffset;
transform.position = position;
}
private static float ClampAngle(float angle, float min, float max)
{
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle, min, max);
}
private List<TouchControl> ActiveTouches(Touchscreen screen)
{
List<TouchControl> i = new List<TouchControl>();
foreach (var item in screen.touches)
{
if (item.isInProgress)
i.Add(item);
}
return i;
}
public void UpdateConfig(Vector3 _targetOffset,float _xDeg,float _yDeg,float _desiredZoomLevel)
{
xDeg = _xDeg;
yDeg = _yDeg;
desiredDistance = _desiredZoomLevel;
targetOffset = _targetOffset;
}
public void InteractionBlock(bool _state)
{
isEnabled = !_state;
Debug.Log("State Updated");
}
}