using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
[RequireComponent(typeof(RectTransform))]
public class RadialSlider : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerDownHandler
{
public SprinklerController sprinklerController; // 스프링클러 컨트롤러
public RectTransform centerPivot; // 회전시킬 피벗 (원점)
public float slideArea = 10f; // 슬라이드 할 수 있는 영역의 거리 (원의 외곽선으로부터의 거리)
[Range(0f, 360f)] public float minAngle = 0f; // 슬라이드 영역 최소 각도
[Range(0f, 360f)] public float maxAngle = 360f; // 슬라이드 영역 최대 각도
private float outerRadius; // 원의 외부 반지름
private float innerRadius; // 원의 내부 반지름 (내부 반지름은 0보다 크고 외부 반지름보다 작아야 함!)
private bool isSlideArea = false; // 슬라이드 영역 내부를 클릭했는지 여부
// Use this for initialization
void Start()
{
outerRadius = ((RectTransform)transform).rect.width / 2f; // 외부 반지름 설정
innerRadius = outerRadius - slideArea; // 내부 반지름 설정
}
// Update is called once per frame
void Update()
{
}
/// <summary>
/// 포인트의 각도를 변환하는 메서드
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
private float GetAngle(Vector2 point)
{
float angle = Mathf.Atan2(point.x, point.y) * Mathf.Rad2Deg;
angle = (angle + 360f) % 360f; // 양수만 나오게 360도를 더한 후 360도로 모듈러 연산 수행
return angle;
}
public void OnBeginDrag(PointerEventData eventData)
{
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
// 드래그를 시작한 포인트가 원의 외부 반지름보다 큰 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y > outerRadius * outerRadius)
return;
// 드래그를 시작한 포인트가 원의 내부 반지름보다 작은 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y < innerRadius * innerRadius)
return;
float angle = GetAngle(point);
if (angle < minAngle || angle > maxAngle)
return;
isSlideArea = true;
}
public void OnDrag(PointerEventData eventData)
{
if (!isSlideArea)
return;
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
if (centerPivot)
{
float angle = GetAngle(point);
if (angle >= minAngle && angle <= maxAngle)
{
centerPivot.localEulerAngles = new Vector3(centerPivot.localEulerAngles.x, centerPivot.localEulerAngles.y, -angle);
sprinklerController.OnValueChangedSprinklerPan(angle); // 스프링클러 팬 회전
}
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (!isSlideArea)
return;
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
if (centerPivot)
{
float angle = GetAngle(point); // 라디안 각도를 도로 변환
// UI의 Z축 회전은 World와 반대이기 때문에 -를 해줌
if (angle >= minAngle && angle <= maxAngle)
{
centerPivot.localEulerAngles = new Vector3(centerPivot.localEulerAngles.x, centerPivot.localEulerAngles.y, -angle);
sprinklerController.OnValueChangedSprinklerPan(angle); // 스프링클러 팬 회전
}
}
isSlideArea = false;
}
public void OnPointerDown(PointerEventData eventData)
{
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out point); // RectTransform의 로컬 포인트로 변환
// 마우스 다운 한 포인트가 원의 외부 반지름보다 큰 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y > outerRadius * outerRadius)
return;
// 마우스 다운 한 포인트가 원의 내부 반지름보다 작은 영역일 경우 실행 안함
if (point.x * point.x + point.y * point.y < innerRadius * innerRadius)
return;
if (centerPivot)
{
float angle = GetAngle(point); // 라디안 각도를 도로 변환
// UI의 Z축 회전은 World와 반대이기 때문에 -를 해줌
if (angle >= minAngle && angle <= maxAngle)
{
centerPivot.localEulerAngles = new Vector3(centerPivot.localEulerAngles.x, centerPivot.localEulerAngles.y, -angle);
sprinklerController.OnValueChangedSprinklerPan(angle); // 스프링클러 팬 회전
}
}
}
public void OnPointerClick(PointerEventData eventData)
{
}
}
댓글 없음:
댓글 쓰기