484 lines
13 KiB
C#
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;
|
|
}
|
|
} |