Project_WL/Assets/Script/UI/JoyStick/UIJoystick.cs

484 lines
13 KiB
C#

#pragma warning disable 0414 // private field assigned but not used. by kts123 2014.11.06
using UnityEngine;
using System.Collections;
using System;
/// <summary>
/// Allows dragging of the specified target object by mouse or touch, optionally limiting it to be within the UIPanel's clipped rectangle.
/// </summary>
[AddComponentMenu("NGUI/Interaction/Drag Object")]
public class UIJoystick : MonoBehaviour
{
static UIJoystick[] joysticks; // A static collection of all joysticks
static bool enumeratedJoysticks = false;
/// <summary>
/// Target object that will be dragged.
/// </summary>
public Transform target;
public Vector3 scale = Vector3.one;
public float radius = 40f; // the radius for the joystick to move
public bool centerOnPress = true;
Vector3 userInitTouchPos = Vector3.zero;
//Joystick vars
public bool normalize = false; // Normalize output after the dead-zone?
public float fadeOutAlpha = 0.2f;
public float fadeOutDelay = 1f;
public UIWidget[] widgetsToFade; // UIWidgets that should fadeIn/Out when centerOnPress = true
public Transform[] widgetsToCenter; // GameObjects to Center under users thumb when centerOnPress = true
public float doubleTapTimeWindow = 0.5f; // time in Seconds to recognize a double tab
public GameObject doubleTapMessageTarget;
public string doubleTabMethodeName;
public float damping = 1.0f;
public Vector3 m_vPressPos = Vector3.zero;
public Vector3 m_vOldPos = Vector2.zero;
public Vector3 m_vCurrentPos = Vector2.zero;
public GameObject RelayTarget = null;
private UIJoystick RelayJoyStick = null;
private Vector3 m_vSpringSpeed = Vector3.zero;
public UIWidget m_pWidget = null;
public DSEvent eventPressTouch = new DSEvent();
public DSEvent eventTouch = new DSEvent();
public DSEvent eventTouchDirection = new DSEvent();
public DSEvent eventStickDirection = new DSEvent();
public DSEvent eventTouchEnd = new DSEvent();
public GameObject[] m_arrDirection;
// ------------------------------------------------------------
// 시스템 콜백 함수들
void Awake()
{
userInitTouchPos = target.position;
SetRelayJoyStick();
}
void Start()
{
userInitTouchPos = target.position;
StartFadeOut();
}
void Update()
{
if (false == enumeratedJoysticks)
{
// Collect all joysticks in the game, so we can relay finger latching messages
joysticks = FindObjectsOfType(typeof(UIJoystick)) as UIJoystick[];
enumeratedJoysticks = true;
}
SetSpringStick();
}
void OnEnable()
{
if (false == this.gameObject.activeInHierarchy)
return;
target.position = userInitTouchPos;
SetPosToWidget(userInitTouchPos);
m_vOldPos = Vector2.zero;
m_vCurrentPos = Vector2.zero;
StartFadeIn();
StartFadeOut();
RelayToEnable();
}
void OnDisable()
{
target.position = userInitTouchPos;
SetPosToWidget(userInitTouchPos);
// ClearEvent();
}
public void OnPress(bool bPressed)
{
if (target == null)
return;
if (true == bPressed)
SetPressToOn();
else
SetPressToOff();
}
void OnDrag(Vector2 delta)
{
if (target == null)
return;
if (0.0f == delta.magnitude)
return;
m_vOldPos = m_vCurrentPos;
m_vCurrentPos = GetPosToTouch();
// OldPos가 Zero(초기화 상태)이면 갑자기 조이스틱이 확 튀어가기 때문에 아래처럼 보완해줌
if (Vector3.zero == m_vOldPos)
m_vOldPos = m_vCurrentPos;
Vector3 vGap = Vector3.zero;
// 현재 손가락 위치 기준
// vGap = GetConvertPosToTouchPos(m_vOldPos, m_vCurrentPos);
// 처음 찍은 위치 기준
vGap = GetConvertPosToTouchPos(m_vPressPos, m_vCurrentPos);
SetTargetDragging(vGap);
SendEventToTouch(vGap);
RelayToDrag();
}
// ------------------------------------------------------------
// 초기화 및 종료 관련 함수들
public void ClearEvent()
{
eventTouch.Clear();
eventPressTouch.Clear();
eventTouchDirection.Clear();
eventStickDirection.Clear();
eventTouchEnd.Clear();
}
// ------------------------------------------------------------
// 내부 유틸함수들
void SetPressToOn()
{
eventPressTouch.CallBack(this);
StopAllCoroutines();
SendMsgToDoubleTabMethode();
TweenColorToFadeWidgets(Color.white, 1.0f, 0.1f, UITweener.Method.EaseIn);
Vector3 vTouchPos = GetPosToTouch();
if (true == centerOnPress)
{
userInitTouchPos = vTouchPos;
}
m_vOldPos = vTouchPos;
m_vCurrentPos = vTouchPos;
m_vPressPos = vTouchPos;
SetPosToWidget(userInitTouchPos);
RelayToPressOn();
}
void SetPressToOff()
{
// Release the finger control and set the joystick back to the default position
// target.position = userInitTouchPos;
SetPosToWidget(userInitTouchPos);
m_vOldPos = Vector3.zero;
m_vCurrentPos = Vector3.zero;
m_vPressPos = Vector3.zero;
StartFadeOut();
SendEventToEnd();
RelayToPressOff();
AllOffDirection();
}
void AllOffDirection()
{
for (int i = 0; i < m_arrDirection.Length; ++i)
{
m_arrDirection[i].SetActive(false);
}
}
void SetTargetDragging(Vector3 vGap)
{
target.localPosition = vGap;
// Calculate the length. This involves a squareroot operation,
// so it's slightly expensive. We re-use this length for multiple
// things below to avoid doing the square-root more than one.
Vector3 vLocalPos = target.localPosition;
float fLength = vLocalPos.magnitude;
// If the length of the vector is smaller than the deadZone radius,
// set the position to the origin.
if (fLength < 2)
vLocalPos = Vector2.zero;
else if (fLength > radius)
vLocalPos = Vector2.ClampMagnitude(vLocalPos, radius);
target.localPosition = widgetsToFade[1].transform.localPosition + vLocalPos;
AllOffDirection();
/* float fAngle = Single.Physics.GetAngleToPositionZ(vLocalPos, Vector3.up);
int iDirection = 0;
if (fAngle < -90)
iDirection = 2;
else if (fAngle < 0)
iDirection = 3;
else if (fAngle > 90)
iDirection = 1;
if(m_arrDirection != null && m_arrDirection.Length > iDirection)
m_arrDirection[iDirection].SetActive(true);*/
}
void SetSpringStick()
{
if (false == IsZeroToTouchPos())
return;
// 아래는 첫 클릭한 위치 기준으로 스프링 효과
// Vector3 vCenterPos = userInitTouchPos;
// 아래는 조이스틱 이미지 기준으로 스프링 효과
Vector3 vCenterPos = widgetsToFade[1].transform.position;
Vector3 vTargetPos = target.position;
target.position = Single.Physics.CalculationSpring(vCenterPos, vTargetPos, ref m_vSpringSpeed, 1000.0f, 20.0f);
RelayToSpringStick();
}
Vector3 GetConvertPosToTouchPos(Vector3 vOldPos, Vector3 vPos)
{
Vector3 vOffset = (vPos - vOldPos);
// 이동 값음 유아이 맨 루트에 보면 스케일만큼 작아진 기준으로 이동 값이 들어옴
// 그래서 그 스케일만큼 뻥튀기 해줘야 유아이상에서 똑같이 이동됨
if (vOffset.x != 0f || vOffset.y != 0f)
{
vOffset = target.InverseTransformDirection(vOffset);
vOffset.Scale(scale);
vOffset = target.TransformDirection(vOffset);
}
vOffset.z = 0.0f;
return vOffset;
}
Vector3 GetTargetNormalize()
{
Vector3 vLocalPos = target.localPosition;
if (false == normalize)
return vLocalPos;
else
return vLocalPos / radius * Mathf.InverseLerp(radius, 0, 1);
}
Vector3 GetPosToTouch()
{
//set Joystick to finger touchposition
Ray ray = UICamera.currentCamera.ScreenPointToRay(UICamera.lastEventPosition);
Vector3 vTouchPos = ray.GetPoint(0.0f);
vTouchPos.z = 0.0f;
return vTouchPos;
}
void SetPosToWidget(Vector3 vPos)
{
foreach (Transform pWidget in widgetsToCenter)
{
pWidget.position = vPos;
}
}
bool IsZeroToTouchPos()
{
return (Vector3.zero == m_vOldPos && Vector3.zero == m_vCurrentPos);
}
// ------------------------------------------------------------
// 릴레이 관련
void SetRelayJoyStick()
{
if (null == RelayTarget)
return;
RelayJoyStick = RelayTarget.GetComponent<UIJoystick>();
}
bool IsRelay()
{
return (null != RelayJoyStick);
}
void RelayToEnable()
{
if (false == IsRelay())
return;
RelayJoyStick.OnEnable();
}
void RelayToPressOn()
{
if (false == IsRelay())
return;
RelayJoyStick.SetRelayToPressOn();
}
void RelayToPressOff()
{
if (false == IsRelay())
return;
RelayJoyStick.SetRelayToPressOff();
}
void RelayToDrag()
{
if (false == IsRelay())
return;
RelayJoyStick.SetRelayToDrag(GetConvertPosToTouchPos(m_vOldPos, m_vCurrentPos));
}
void RelayToSpringStick()
{
if (false == IsRelay())
return;
RelayJoyStick.SetSpringStick();
}
void SetRelayToPressOn()
{
StopAllCoroutines();
SendMsgToDoubleTabMethode();
TweenColorToFadeWidgets(Color.white, 1.0f, 0.1f, UITweener.Method.EaseIn);
m_vOldPos = userInitTouchPos;
m_vCurrentPos = userInitTouchPos;
SetPosToWidget(userInitTouchPos);
}
void SetRelayToPressOff()
{
SetPressToOff();
}
public void SetRelayToDrag(Vector3 vGap)
{
m_vOldPos = m_vCurrentPos;
m_vCurrentPos = m_vOldPos + vGap;
SetTargetDragging(vGap);
SendEventToTouch(vGap);
}
// ------------------------------------------------------------
// 이벤트 관련
void SendEventToTouch(Vector2 vPos)
{
eventTouch.CallBack<Vector2>(this, vPos);
eventTouchDirection.CallBack<Vector2>(this, vPos.normalized);
//Vector3 vStickPos = target.localPosition;
eventStickDirection.CallBack<Vector2>(this, vPos.normalized);
}
void SendEventToEnd()
{
eventTouchEnd.CallBack(this);
}
void SendMsgToDoubleTabMethode()
{
if (Time.deltaTime >= doubleTapTimeWindow)
return;
if (null == doubleTapMessageTarget)
return;
if ("" == doubleTabMethodeName)
return;
doubleTapMessageTarget.SendMessage(doubleTabMethodeName, SendMessageOptions.DontRequireReceiver);
}
// --------------------------------------------
// 등록된 위젯오브젝트들의 페이드 관련
void StartFadeIn()
{
if (false == this.gameObject.activeInHierarchy)
return;
StartCoroutine(FadeInJoystick());
}
void StartFadeOut()
{
if (false == this.gameObject.activeInHierarchy)
return;
StartCoroutine(FadeOutJoystick());
}
IEnumerator FadeInJoystick()
{
foreach (UIWidget widget in widgetsToFade)
widget.color = GetAlphaColor(widget.color, fadeOutAlpha);
yield return null;
TweenColorToFadeWidgets(Color.white, 1.0f, 0.1f, UITweener.Method.EaseIn);
}
IEnumerator FadeOutJoystick()
{
yield return new WaitForSeconds(fadeOutDelay);
TweenColorToFadeWidgets(null, fadeOutAlpha, 0.5f, UITweener.Method.EaseOut);
}
Color GetAlphaColor(Color pColor, float fAlpha)
{
pColor.a = fAlpha;
return pColor;
}
void TweenColorToFadeWidgets(Color? pColor, float fAlpha, float fDuration, UITweener.Method eMethod)
{
// Add FadeIn Color without CenterOnPress Option[blueasa / 2014-11-08]
foreach (UIWidget widget in widgetsToFade)
{
if (null == pColor)
pColor = GetAlphaColor(widget.color, fAlpha);
TweenColor.Begin(widget.gameObject, fDuration, pColor.Value).method = eMethod;
}
}
public void SetAlpha(float fRValue)
{
if (null == m_pWidget)
return;
m_pWidget.alpha = fRValue;
}
}