424 lines
13 KiB
C#
424 lines
13 KiB
C#
using RTGLite;
|
||
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.EventSystems;
|
||
using DG.Tweening;
|
||
using System.Collections.Generic;
|
||
|
||
namespace OCTOPUS_TWIN
|
||
{
|
||
public enum ViewMode
|
||
{
|
||
PerspectiveView,
|
||
TopView
|
||
}
|
||
public struct OrbitState
|
||
{
|
||
public float elevation;
|
||
public float distance;
|
||
public float azimuth;
|
||
public Vector3 pivotPosition;
|
||
public Quaternion pivotRotation;
|
||
}
|
||
|
||
//TODO::Something... Util Functions
|
||
public class OrbitalController : MonoBehaviour
|
||
{
|
||
public ViewMode viewMode;
|
||
private Vector3 originValue;
|
||
private Vector3 originTargetPos;
|
||
|
||
private OrbitState perspectiveState;
|
||
private OrbitState orthoState;
|
||
|
||
private new Camera camera;
|
||
|
||
public Camera Camera { get { return camera; } }
|
||
|
||
public float moveSpeed;
|
||
public float rotateSpeed;
|
||
public float zoomSpeed;
|
||
|
||
public float maxElevation;
|
||
public float minElevation;
|
||
public float minDistance;
|
||
public float maxDistance;
|
||
public float currentElevation;
|
||
public float currentDistance;
|
||
public float currentAzimuth;
|
||
|
||
private Vector3 cameraPosition;
|
||
private Vector3 nextPosition;
|
||
private Quaternion originRotation;
|
||
public OrbitalControllerTarget cameraPivot;
|
||
|
||
private UserInput input;
|
||
|
||
public Action<ViewMode> onChangeViewMode;
|
||
|
||
public bool IsCameraOperating { get; private set; }
|
||
private bool isMoveOperation;
|
||
private bool isRotateOperation;
|
||
private bool isZoomOperation;
|
||
|
||
public bool Enable;
|
||
public bool IsRouteActive => routeSequence != null && routeSequence.IsActive();
|
||
private Sequence routeSequence;
|
||
|
||
public bool IsClickUI
|
||
{
|
||
get
|
||
{
|
||
bool result = false;
|
||
if (Input.GetMouseButtonDown(0))
|
||
{
|
||
result = EventSystem.current.IsPointerOverGameObject();
|
||
}
|
||
|
||
return result;
|
||
}
|
||
}
|
||
|
||
public bool IsOnTheUI
|
||
{
|
||
get
|
||
{
|
||
if (IsPointerOverExcludedUI())
|
||
{
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
var result = EventSystem.current.IsPointerOverGameObject();
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
bool IsPointerOverExcludedUI()
|
||
{
|
||
PointerEventData pointerData = new PointerEventData(EventSystem.current);
|
||
pointerData.position = Input.mousePosition;
|
||
|
||
List<RaycastResult> raycastResults = new List<RaycastResult>();
|
||
EventSystem.current.RaycastAll(pointerData, raycastResults);
|
||
|
||
if (raycastResults.Count > 0)
|
||
{
|
||
if ((LayerMask.GetMask("Default") & (1 << raycastResults[0].gameObject.layer)) != 0)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public void Awake()
|
||
{
|
||
camera = Camera.main;
|
||
cameraPivot = transform.GetComponentInChildren<OrbitalControllerTarget>();
|
||
}
|
||
void Start()
|
||
{
|
||
originValue.x = currentElevation;
|
||
originValue.y = currentDistance;
|
||
originValue.z = currentAzimuth;
|
||
|
||
nextPosition = cameraPivot.transform.position;
|
||
originTargetPos = cameraPivot.transform.position;
|
||
|
||
originRotation = cameraPivot.transform.rotation;
|
||
|
||
perspectiveState.elevation = originValue.x;
|
||
perspectiveState.distance = originValue.y;
|
||
perspectiveState.azimuth = originValue.z;
|
||
perspectiveState.pivotPosition = originTargetPos;
|
||
perspectiveState.pivotRotation = originRotation;
|
||
|
||
orthoState.elevation = 90f;
|
||
orthoState.distance = originValue.y;
|
||
orthoState.azimuth = 0f;
|
||
orthoState.pivotPosition = Vector3.zero;
|
||
orthoState.pivotRotation = originRotation;
|
||
SetViewMode(ViewMode.PerspectiveView);
|
||
}
|
||
|
||
public void SetEnable(bool isDrag)
|
||
{
|
||
Enable = !isDrag;
|
||
}
|
||
|
||
|
||
private void LateUpdate()
|
||
{
|
||
//UI <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ī<><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
if (IsClickUI || IsOnTheUI)
|
||
return;
|
||
|
||
//<2F><><EFBFBD>̺귯<CCBA><EAB7AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><>ġ<EFBFBD><C4A1> ī<><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
if (!Enable)
|
||
{
|
||
return;
|
||
}
|
||
if (RTGizmos.get !=null )
|
||
{
|
||
if (RTGizmos.get.draggedGizmo != null)
|
||
return;
|
||
if (RTGizmos.get.hoveredGizmo != null)
|
||
return;
|
||
}
|
||
input.GetInput();
|
||
Movement();
|
||
}
|
||
|
||
public void Movement()
|
||
{
|
||
Zoom();
|
||
Rotate();
|
||
Move();
|
||
|
||
UpdateOperationState();
|
||
LastPositioning();
|
||
}
|
||
|
||
private void Move()
|
||
{
|
||
if (!input.leftClick)
|
||
{
|
||
isMoveOperation = false;
|
||
return;
|
||
}
|
||
|
||
var delta = new Vector2(input.mouseX, input.mouseY);
|
||
var x = delta.x;
|
||
var y = delta.y * ((maxElevation - minElevation) / currentElevation);
|
||
var z = delta.y * ((minElevation - currentElevation) / maxElevation);
|
||
|
||
var moveVector = camera.transform.TransformDirection(x, y, -z);
|
||
moveVector.y = 0;
|
||
|
||
//moveVector *= moveSpeed * (currentDistance / maxDistance);
|
||
nextPosition = cameraPivot.transform.position - moveVector;
|
||
isMoveOperation = true;
|
||
}
|
||
|
||
private void Zoom()
|
||
{
|
||
if (Mathf.Abs(input.mouseWheel) > 0.0001f)
|
||
{
|
||
isZoomOperation = true;
|
||
}
|
||
else
|
||
{
|
||
isZoomOperation = false;
|
||
return;
|
||
}
|
||
|
||
var nextDistance = currentDistance - input.mouseWheel * zoomSpeed;
|
||
currentDistance = Mathf.Lerp(currentDistance, nextDistance, zoomSpeed * Time.deltaTime);
|
||
currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);
|
||
|
||
camera.orthographicSize = currentDistance;
|
||
}
|
||
|
||
protected void Rotate()
|
||
{
|
||
if (!input.rightClick)
|
||
{
|
||
isRotateOperation = false;
|
||
return;
|
||
}
|
||
|
||
|
||
currentAzimuth += input.mouseX * rotateSpeed;
|
||
currentAzimuth %= 360;
|
||
|
||
if(viewMode == ViewMode.PerspectiveView)
|
||
{
|
||
currentElevation -= input.mouseY * rotateSpeed;
|
||
currentElevation = Mathf.Clamp(currentElevation, minElevation, maxElevation);
|
||
}
|
||
isRotateOperation = true;
|
||
}
|
||
|
||
private void UpdateOperationState()
|
||
{
|
||
IsCameraOperating = isMoveOperation || isRotateOperation || isZoomOperation;
|
||
}
|
||
|
||
public void LastPositioning()
|
||
{
|
||
cameraPivot.transform.position = nextPosition;
|
||
var dist = new Vector3(0, 0, -currentDistance);
|
||
var distPos = Quaternion.Euler(currentElevation, currentAzimuth, 0f) * dist;
|
||
cameraPosition = nextPosition + distPos;
|
||
camera.transform.position = cameraPosition;
|
||
|
||
if (currentElevation <= 90f)
|
||
{
|
||
camera.transform.rotation = Quaternion.Euler(currentElevation, currentAzimuth, 0f);
|
||
}
|
||
else
|
||
{
|
||
camera.transform.LookAt(cameraPivot.transform);
|
||
}
|
||
}
|
||
|
||
public void Rewind()
|
||
{
|
||
SetViewMode(ViewMode.PerspectiveView);
|
||
nextPosition = originTargetPos;
|
||
|
||
currentDistance = originValue.x;
|
||
currentElevation = originValue.y;
|
||
currentAzimuth = originValue.z;
|
||
|
||
LastPositioning();
|
||
}
|
||
|
||
public void SetViewMode(ViewMode mode)
|
||
{
|
||
if (viewMode == mode)
|
||
return;
|
||
|
||
SaveViewMode(viewMode);
|
||
viewMode = mode;
|
||
|
||
switch (mode)
|
||
{
|
||
case ViewMode.PerspectiveView:
|
||
SetPerspectiveView();
|
||
break;
|
||
|
||
case ViewMode.TopView:
|
||
SetOrthographicView();
|
||
break;
|
||
}
|
||
LastPositioning();
|
||
onChangeViewMode?.Invoke(viewMode);
|
||
}
|
||
private void SetPerspectiveView()
|
||
{
|
||
camera.orthographic = false;
|
||
|
||
currentElevation = perspectiveState.elevation; //90 <20><> <20><><EFBFBD><EFBFBD>
|
||
currentDistance = perspectiveState.distance;
|
||
currentAzimuth = perspectiveState.azimuth;
|
||
|
||
nextPosition = perspectiveState.pivotPosition;
|
||
}
|
||
private void SetOrthographicView()
|
||
{
|
||
camera.orthographic = true;
|
||
|
||
currentElevation = orthoState.elevation;
|
||
currentDistance = orthoState.distance;
|
||
currentAzimuth = orthoState.azimuth;
|
||
camera.orthographicSize = orthoState.distance;
|
||
|
||
nextPosition = orthoState.pivotPosition;
|
||
}
|
||
|
||
public void SetTargetPos(Vector3 pos)
|
||
{
|
||
nextPosition = pos;
|
||
LastPositioning();
|
||
}
|
||
|
||
public void SetTargetRotation(Quaternion rotation)
|
||
{
|
||
originRotation = rotation;
|
||
}
|
||
|
||
private void SaveViewMode(ViewMode mode)
|
||
{
|
||
switch (mode)
|
||
{
|
||
case ViewMode.PerspectiveView:
|
||
perspectiveState.elevation = currentElevation;
|
||
perspectiveState.distance = currentDistance;
|
||
perspectiveState.azimuth = currentAzimuth;
|
||
perspectiveState.pivotPosition = cameraPivot.transform.position;
|
||
break;
|
||
|
||
case ViewMode.TopView:
|
||
orthoState.elevation = 90f; // 90 or <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
orthoState.distance = 60f;
|
||
orthoState.azimuth = 0f;
|
||
orthoState.pivotPosition = Vector3.zero;
|
||
break;
|
||
}
|
||
}
|
||
|
||
internal void SetControllOptionValue()
|
||
{
|
||
throw new NotImplementedException();
|
||
}
|
||
|
||
public void SetRoute(CameraRoute route)
|
||
{
|
||
StopRoute();
|
||
Enable = false;
|
||
|
||
routeSequence = DOTween.Sequence();
|
||
|
||
for (int i = 0; i < route.PointCount; i++)
|
||
{
|
||
var (position, point) = route.GetWaypoint(i);
|
||
|
||
float elev = point != null ? point.elevation : currentElevation;
|
||
float azi = point != null ? point.azimuth : currentAzimuth;
|
||
float dist = point != null ? point.distance : currentDistance;
|
||
float dur = point != null ? point.duration : 0.5f;
|
||
float wait = point != null ? point.waitTime : 0f;
|
||
|
||
routeSequence.Append(
|
||
DOTween.To(() => nextPosition, x => nextPosition = x, position, dur));
|
||
routeSequence.Join(
|
||
DOTween.To(() => currentElevation, x => currentElevation = x, elev, dur));
|
||
routeSequence.Join(
|
||
DOTween.To(() => currentAzimuth, x => currentAzimuth = x, azi, dur));
|
||
routeSequence.Join(
|
||
DOTween.To(() => currentDistance, x => currentDistance = x, dist, dur));
|
||
|
||
if (wait > 0f)
|
||
routeSequence.AppendInterval(wait);
|
||
}
|
||
|
||
if (route.loop)
|
||
routeSequence.SetLoops(-1, LoopType.Restart);
|
||
|
||
routeSequence.OnUpdate(LastPositioning);
|
||
routeSequence.OnKill(() => Enable = true);
|
||
}
|
||
|
||
public void StopRoute()
|
||
{
|
||
if (routeSequence != null && routeSequence.IsActive())
|
||
{
|
||
routeSequence.Kill();
|
||
routeSequence = null;
|
||
}
|
||
}
|
||
|
||
public void AnimateToState(Vector3 pivotPosition, Vector3 eulerAngles, float distance, float duration = 0.4f)
|
||
{
|
||
// <20>ִϸ<D6B4><CFB8>̼<EFBFBD> <20>߿<EFBFBD><DFBF><EFBFBD> <20><><EFBFBD>콺 <20>Է<EFBFBD> <20><>Ȱ<EFBFBD><C8B0>ȭ
|
||
Enable = false;
|
||
|
||
// DoTween<65><6E> <20><><EFBFBD><EFBFBD>Ͽ<EFBFBD> <20><>Ʈ<EFBFBD>ѷ<EFBFBD><D1B7><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε巴<CEB5><E5B7B4> <20><><EFBFBD><EFBFBD>
|
||
DOTween.To(() => nextPosition, x => nextPosition = x, pivotPosition, duration);
|
||
DOTween.To(() => currentElevation, x => currentElevation = x, eulerAngles.x, duration);
|
||
DOTween.To(() => currentAzimuth, x => currentAzimuth = x, eulerAngles.y, duration);
|
||
DOTween.To(() => currentDistance, x => currentDistance = x, distance, duration)
|
||
.OnComplete(() => {
|
||
// <20>ִϸ<D6B4><CFB8>̼<EFBFBD><CCBC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>콺 <20>Է<EFBFBD><D4B7><EFBFBD> <20>ٽ<EFBFBD> Ȱ<><C8B0>ȭ
|
||
Enable = true;
|
||
});
|
||
}
|
||
|
||
//public bool IsOperation()
|
||
//{
|
||
// if(is)
|
||
//}
|
||
}
|
||
} |