290 lines
7.2 KiB
C#
290 lines
7.2 KiB
C#
using GISTech.GISTerrainLoader;
|
|
using UnityEngine;
|
|
|
|
public class Camera3D : MonoBehaviour
|
|
{
|
|
public KeyCode RotateLeft;
|
|
|
|
public KeyCode RotateRight;
|
|
|
|
public KeyCode ResetCameraPosKey;
|
|
|
|
[Header("Adapte Camera to GIS Container")]
|
|
public bool AdapteToGISContainer;
|
|
|
|
[Header("Camera Movements")]
|
|
public float PanSpeed = 0.1f;
|
|
|
|
public float RotationSpeed = 0.15f;
|
|
|
|
public float ZoomSpeed;
|
|
|
|
public float FollowSpeed = 0.1f;
|
|
|
|
public float SmoothingFactor = 0.1f;
|
|
|
|
[Header("Camera Parameters")]
|
|
[Space(4f)]
|
|
public bool UseKeyboardInput = true;
|
|
|
|
public bool UseMouseInput = true;
|
|
|
|
public bool AdaptToTerrainHeight = true;
|
|
|
|
public bool IncreaseSpeedWhenZoomedOut = true;
|
|
|
|
public bool CorrectZoomingOutRatio = true;
|
|
|
|
public bool Smoothing = true;
|
|
|
|
[Header("Follow a GameObject")]
|
|
public GameObject TargetToFollow;
|
|
|
|
[Header("Enable/Disbale Position On Start")]
|
|
public bool UseStartPosition;
|
|
|
|
public Vector3 StartPosition;
|
|
|
|
public Vector3 StartRotation;
|
|
|
|
private float mousepanSpeed = 15f;
|
|
|
|
private float mousezoomSpeed = 100f;
|
|
|
|
private Vector2 MinMaxZoom = new Vector2(0f, 0f);
|
|
|
|
private float minZoomDistance = 20f;
|
|
|
|
private float maxZoomDistance = 2f;
|
|
|
|
private Vector3 cameraTarget;
|
|
|
|
private float currentCameraDistance;
|
|
|
|
private Vector3 lastMousePos;
|
|
|
|
private Vector3 lastPanSpeed = Vector3.zero;
|
|
|
|
private Vector3 goingToCameraTarget = Vector3.zero;
|
|
|
|
private bool doingAutoMovement;
|
|
|
|
private Vector3 lastpos;
|
|
|
|
private Rect bound;
|
|
|
|
private GISTerrainContainer container;
|
|
|
|
private void OnEnable()
|
|
{
|
|
RuntimeTerrainGenerator.OnFinish += OnTerrainGenerated;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
RuntimeTerrainGenerator.OnFinish -= OnTerrainGenerated;
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
currentCameraDistance = minZoomDistance + (maxZoomDistance - minZoomDistance) / 2f;
|
|
base.transform.position = lastpos;
|
|
if (UseStartPosition)
|
|
{
|
|
GoTo(StartPosition);
|
|
base.transform.localEulerAngles = StartRotation;
|
|
}
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (Input.GetKeyDown(ResetCameraPosKey))
|
|
{
|
|
ResetCameraPosition();
|
|
}
|
|
UpdatePanning();
|
|
UpdateZooming();
|
|
UpdatePosition();
|
|
UpdateAutoMovement();
|
|
lastMousePos = Input.mousePosition;
|
|
}
|
|
|
|
public void GoTo(Vector3 position)
|
|
{
|
|
doingAutoMovement = true;
|
|
goingToCameraTarget = position;
|
|
TargetToFollow = null;
|
|
}
|
|
|
|
public void Follow(GameObject gameObjectToFollow)
|
|
{
|
|
TargetToFollow = gameObjectToFollow;
|
|
}
|
|
|
|
private void UpdatePanning()
|
|
{
|
|
Vector3 vector = new Vector3(0f, 0f, 0f);
|
|
if (UseKeyboardInput)
|
|
{
|
|
if (Input.GetKey(KeyCode.LeftArrow))
|
|
{
|
|
vector.x -= 1f;
|
|
}
|
|
if (Input.GetKey(KeyCode.DownArrow))
|
|
{
|
|
vector.z -= 1f;
|
|
}
|
|
if (Input.GetKey(KeyCode.RightArrow))
|
|
{
|
|
vector.x += 1f;
|
|
}
|
|
if (Input.GetKey(KeyCode.UpArrow))
|
|
{
|
|
vector.z += 1f;
|
|
}
|
|
}
|
|
if (UseMouseInput)
|
|
{
|
|
if (Input.GetMouseButton(0))
|
|
{
|
|
Vector3 vector2 = Input.mousePosition - lastMousePos;
|
|
vector += new Vector3(0f - vector2.x, 0f, 0f - vector2.y) * PanSpeed;
|
|
}
|
|
if (Input.GetMouseButton(2))
|
|
{
|
|
vector += new Vector3(0f, 0f - (Input.mousePosition - lastMousePos).y, 0f) * PanSpeed;
|
|
}
|
|
}
|
|
if (vector != Vector3.zero)
|
|
{
|
|
TargetToFollow = null;
|
|
doingAutoMovement = false;
|
|
}
|
|
Vector3 direction = vector;
|
|
if (Smoothing)
|
|
{
|
|
direction = (lastPanSpeed = Vector3.Lerp(lastPanSpeed, vector, SmoothingFactor));
|
|
}
|
|
float x = base.transform.localEulerAngles.x;
|
|
base.transform.SetLocalEulerAngles(0f);
|
|
float num = (IncreaseSpeedWhenZoomedOut ? Mathf.Sqrt(currentCameraDistance) : 1f);
|
|
cameraTarget += base.transform.TransformDirection(direction) * mousepanSpeed * num * Time.deltaTime;
|
|
base.transform.SetLocalEulerAngles(x);
|
|
}
|
|
|
|
private void UpdateZooming()
|
|
{
|
|
float num = 0f;
|
|
if (UseKeyboardInput)
|
|
{
|
|
if (Input.GetKey(KeyCode.F))
|
|
{
|
|
num = 1f;
|
|
}
|
|
if (Input.GetKey(KeyCode.R))
|
|
{
|
|
num = -1f;
|
|
}
|
|
}
|
|
if (!UseMouseInput)
|
|
{
|
|
return;
|
|
}
|
|
float axis = Input.GetAxis("Mouse ScrollWheel");
|
|
num -= axis * ZoomSpeed;
|
|
float num2 = (CorrectZoomingOutRatio ? ((currentCameraDistance - minZoomDistance) / (maxZoomDistance - minZoomDistance)) : 0f);
|
|
if (axis > 0f || axis < 0f)
|
|
{
|
|
float num3 = minZoomDistance * axis * ZoomSpeed * Time.deltaTime;
|
|
if (axis < 0f && minZoomDistance - num3 < MinMaxZoom.y)
|
|
{
|
|
minZoomDistance -= num3;
|
|
}
|
|
if (axis > 0f && minZoomDistance + num3 > MinMaxZoom.x)
|
|
{
|
|
minZoomDistance -= num3;
|
|
}
|
|
if (minZoomDistance <= MinMaxZoom.x)
|
|
{
|
|
minZoomDistance = MinMaxZoom.x;
|
|
}
|
|
float num4 = Mathf.Clamp(Mathf.Max(minZoomDistance, Mathf.Min(maxZoomDistance, currentCameraDistance + num * Time.deltaTime * mousezoomSpeed * (num2 * 2f + 1f))), MinMaxZoom.x, MinMaxZoom.y);
|
|
currentCameraDistance = num4;
|
|
}
|
|
}
|
|
|
|
private void UpdatePosition()
|
|
{
|
|
if (TargetToFollow != null && FollowSpeed > 0f)
|
|
{
|
|
cameraTarget = Vector3.Lerp(cameraTarget, TargetToFollow.transform.position, FollowSpeed);
|
|
}
|
|
if (base.transform.position != Vector3.zero && cameraTarget != Vector3.zero)
|
|
{
|
|
base.transform.position = cameraTarget;
|
|
base.transform.Translate(Vector3.back * currentCameraDistance);
|
|
}
|
|
if (AdapteToGISContainer)
|
|
{
|
|
if (cameraTarget.y >= MinMaxZoom.y)
|
|
{
|
|
cameraTarget = new Vector3(cameraTarget.x, MinMaxZoom.y, cameraTarget.z);
|
|
}
|
|
if (cameraTarget.x <= MinMaxZoom.x)
|
|
{
|
|
cameraTarget = new Vector3(cameraTarget.x, MinMaxZoom.x, cameraTarget.z);
|
|
}
|
|
float x = Mathf.Clamp(base.transform.position.x, bound.xMin, bound.xMax);
|
|
float y = Mathf.Clamp(base.transform.position.y, MinMaxZoom.x, MinMaxZoom.y);
|
|
float z = Mathf.Clamp(base.transform.position.z, bound.yMin, bound.yMax);
|
|
base.transform.position = new Vector3(x, y, z);
|
|
}
|
|
}
|
|
|
|
private void UpdateAutoMovement()
|
|
{
|
|
if (doingAutoMovement)
|
|
{
|
|
cameraTarget = Vector3.Lerp(cameraTarget, goingToCameraTarget, FollowSpeed);
|
|
if (Vector3.Distance(goingToCameraTarget, cameraTarget) < 1f)
|
|
{
|
|
doingAutoMovement = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
if (AdapteToGISContainer)
|
|
{
|
|
Vector3 position = base.transform.position;
|
|
Gizmos.DrawLine(new Vector3(bound.xMin, position.y, bound.yMin), new Vector3(bound.xMin, position.y, bound.yMax));
|
|
Gizmos.DrawLine(new Vector3(bound.xMin, position.y, bound.yMax), new Vector3(bound.xMax, position.y, bound.yMax));
|
|
Gizmos.DrawLine(new Vector3(bound.xMax, position.y, bound.yMax), new Vector3(bound.xMax, position.y, bound.yMin));
|
|
Gizmos.DrawLine(new Vector3(bound.xMax, position.y, bound.yMin), new Vector3(bound.xMin, position.y, bound.yMin));
|
|
}
|
|
}
|
|
|
|
private void OnTerrainGenerated(GISTerrainContainer m_container)
|
|
{
|
|
container = m_container;
|
|
ResetCameraPosition();
|
|
}
|
|
|
|
public void ResetCameraPosition()
|
|
{
|
|
if (container != null)
|
|
{
|
|
bound = new Rect(new Vector2((0f - container.ContainerSize.x) / 2f, (0f - container.ContainerSize.z) / 2f), new Vector2(container.ContainerSize.x * 2f, container.ContainerSize.z * 2f));
|
|
Vector3 position = (cameraTarget = new Vector3(container.ContainerSize.x / 2f, (container.ContainerSize.x + container.ContainerSize.z) / 4f, container.ContainerSize.z / 2f));
|
|
base.transform.position = position;
|
|
lastpos = position;
|
|
base.enabled = true;
|
|
PanSpeed = container.Scale.x * 2f;
|
|
ZoomSpeed = container.Scale.x * 300f;
|
|
MinMaxZoom.x = 40f;
|
|
MinMaxZoom.y = (container.ContainerSize.x + container.ContainerSize.z) / 2f;
|
|
}
|
|
}
|
|
}
|