Created
August 24, 2017 02:37
-
-
Save baba-s/04134481224440d63022a20409b1b9f7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using HedgehogTeam.EasyTouch; | |
using System; | |
using System.Collections; | |
using UnityEngine; | |
/// <summary> | |
/// カメラのタッチ制御を管理するクラス | |
/// </summary> | |
public sealed class TouchManager : MonoBehaviour | |
{ | |
//============================================================================== | |
// 列挙型 | |
//============================================================================== | |
[Flags] | |
private enum State | |
{ | |
NONE = 1 << 0, // 待機 | |
MOVE = 1 << 1, // 移動 | |
ROTATE = 1 << 2, // 回転 | |
ZOOM_IN = 1 << 3, // 拡大 | |
ZOOM_OUT = 1 << 4, // 拡大 | |
} | |
//============================================================================== | |
// 変数(SerializeField) | |
//============================================================================== | |
[SerializeField] private Transform m_cameraAxis = null ; // カメラの軸 | |
[SerializeField] private Camera m_camera = null ; // カメラ本体 | |
[SerializeField] private float m_moveSpeed = 0.5f ; // 移動速度 | |
[SerializeField] private float m_rotateSpeed = 10 ; // 回転速度 | |
[SerializeField] private float m_zoomSpeed = 2.5f ; // 拡大速度 | |
[SerializeField] private float m_minPosX = -1 ; // X 座標の最小値 | |
[SerializeField] private float m_maxPosX = 1 ; // X 座標の最大値 | |
[SerializeField] private float m_minPosY = -1 ; // Y 座標の最小値 | |
[SerializeField] private float m_maxPosY = 1 ; // Y 座標の最大値 | |
[SerializeField] private float m_minFieldOfView = 6 ; // 視野角の最小値 | |
[SerializeField] private float m_maxFieldOfView = 60 ; // 視野角の最大値 | |
[SerializeField] private float m_minRotateX = -85 ; // X 軸方向の回転角の最小値 | |
[SerializeField] private float m_maxRotateX = 15 ; // X 軸方向の回転角の最大値 | |
#if UNITY_EDITOR | |
[SerializeField] private float m_mouseSpeed = 10 ; // マウスの速さ | |
[SerializeField] private float m_wheelSpeed = -500 ; // マウスホイールの速さ | |
#endif | |
//============================================================================== | |
// 変数 | |
//============================================================================== | |
private State m_state ; // ステート | |
private bool m_isPortrait; // 縦持ちの場合 true | |
private Vector3 m_defaultCameraAxisPos ; | |
private Vector3 m_defaultCameraAxisRotate ; | |
private Vector3 m_defaultCameraPos ; | |
private Vector3 m_defaultCameraRotate ; | |
private float m_defaultFieldOfView ; | |
//============================================================================== | |
// プロパティ | |
//============================================================================== | |
public bool IsReverseHorizontal { private get; set; } // カメラの左右操作をリバースする場合 true を設定します | |
public bool IsReverseVertical { private get; set; } // カメラの上下操作をリバースする場合 true を設定します | |
private float deltaTime { get { return Time.deltaTime * ( 1 / Time.timeScale ); } } | |
//============================================================================== | |
// 関数 | |
//============================================================================== | |
/// <summary> | |
/// 初期化する時に呼び出されます | |
/// </summary> | |
private void Awake() | |
{ | |
m_defaultCameraAxisPos = m_cameraAxis.transform.localPosition ; | |
m_defaultCameraAxisRotate = m_cameraAxis.transform.localEulerAngles ; | |
m_defaultCameraPos = m_camera.transform.localPosition ; | |
m_defaultCameraRotate = m_camera.transform.localEulerAngles ; | |
m_defaultFieldOfView = m_camera.fieldOfView ; | |
} | |
/// <summary> | |
/// 有効になる時に呼び出されます | |
/// </summary> | |
private void OnEnable() | |
{ | |
EasyTouch.On_TouchUp2Fingers += On_TouchUp2Fingers ; | |
EasyTouch.On_SwipeStart2Fingers += On_SwipeStart2Fingers ; | |
EasyTouch.On_Swipe2Fingers += On_Swipe2Fingers ; | |
EasyTouch.On_SwipeEnd2Fingers += On_SwipeEnd2Fingers ; | |
EasyTouch.On_SwipeStart += On_SwipeStart ; | |
EasyTouch.On_Swipe += On_Swipe ; | |
EasyTouch.On_SwipeEnd += On_SwipeEnd ; | |
EasyTouch.On_PinchIn += On_PinchIn ; | |
EasyTouch.On_PinchOut += On_PinchOut ; | |
} | |
/// <summary> | |
/// 無効になる時に呼び出されます | |
/// </summary> | |
private void OnDisable() | |
{ | |
EasyTouch.On_TouchUp2Fingers -= On_TouchUp2Fingers ; | |
EasyTouch.On_SwipeStart2Fingers -= On_SwipeStart2Fingers ; | |
EasyTouch.On_Swipe2Fingers -= On_Swipe2Fingers ; | |
EasyTouch.On_SwipeEnd2Fingers -= On_SwipeEnd2Fingers ; | |
EasyTouch.On_SwipeStart -= On_SwipeStart ; | |
EasyTouch.On_Swipe -= On_Swipe ; | |
EasyTouch.On_SwipeEnd -= On_SwipeEnd ; | |
EasyTouch.On_PinchIn -= On_PinchIn ; | |
EasyTouch.On_PinchOut -= On_PinchOut ; | |
} | |
/// <summary> | |
/// 2 本指の両方もしくは片方が離れた時に呼び出されます | |
/// </summary> | |
private void On_TouchUp2Fingers( Gesture gesture ) | |
{ | |
RemoveState( State.MOVE ); | |
} | |
/// <summary> | |
/// 2 本指のスワイプを開始した時に呼び出されます | |
/// </summary> | |
private void On_SwipeStart2Fingers( Gesture gesture ) | |
{ | |
AddState( State.MOVE ); | |
} | |
/// <summary> | |
/// 2 本指のスワイプ中に呼び出されます | |
/// </summary> | |
private void On_Swipe2Fingers( Gesture gesture ) | |
{ | |
Move( gesture.deltaPosition ); | |
} | |
/// <summary> | |
/// 移動します | |
/// </summary> | |
private void Move( Vector2 deltaPosition ) | |
{ | |
var posZ = m_camera.fieldOfView; | |
var zoomRate = Mathf.InverseLerp( m_maxFieldOfView, m_minFieldOfView, posZ ); | |
var speedDelta = Mathf.Lerp( 1, 0.05f, zoomRate ); | |
var delta = deltaTime * deltaPosition * m_moveSpeed * speedDelta; | |
var moveX = m_isPortrait ? -delta.y : -delta.x; | |
var moveY = m_isPortrait ? -delta.x : delta.y; | |
var posX = m_camera.transform.localPosition.x + moveX; | |
var posY = m_camera.transform.localPosition.y + moveY; | |
posX = Mathf.Clamp( posX, m_minPosX, m_maxPosX ); | |
posY = Mathf.Clamp( posY, m_minPosY, m_maxPosY ); | |
var pos = m_camera.transform.localPosition; | |
pos.x = posX; | |
pos.y = posY; | |
m_camera.transform.localPosition = pos; | |
} | |
/// <summary> | |
/// 2 本指のスワイプが終了した時に呼び出されます | |
/// </summary> | |
private void On_SwipeEnd2Fingers( Gesture gesture ) | |
{ | |
RemoveState( State.MOVE ); | |
} | |
/// <summary> | |
/// スワイプを開始した時に呼び出されます | |
/// </summary> | |
private void On_SwipeStart( Gesture gesture ) | |
{ | |
if ( HasFlag( m_state, State.MOVE ) ) return; | |
if ( HasFlag( m_state, State.ZOOM_IN ) ) return; | |
if ( HasFlag( m_state, State.ZOOM_OUT ) ) return; | |
AddState( State.ROTATE ); | |
} | |
/// <summary> | |
/// スワイプ中に呼び出されます | |
/// </summary> | |
private void On_Swipe( Gesture gesture ) | |
{ | |
if ( HasFlag( m_state, State.MOVE ) ) return; | |
if ( HasFlag( m_state, State.ZOOM_IN ) ) return; | |
if ( HasFlag( m_state, State.ZOOM_OUT ) ) return; | |
if ( !HasFlag( m_state, State.ROTATE ) ) | |
{ | |
AddState( State.ROTATE ); | |
} | |
// 縦持ち:portrait | |
// 横持ち:landscape | |
var delta = deltaTime * gesture.deltaPosition * m_rotateSpeed; | |
var rotate = m_cameraAxis.transform.localEulerAngles; | |
var rateX = m_isPortrait ? -delta.x : delta.y; | |
var rateY = m_isPortrait ? -delta.y : -delta.x; | |
rotate.x += IsReverseVertical ? -rateX : rateX; // 縦方向 | |
rotate.y += IsReverseHorizontal ? rateY : -rateY; // 横方向 | |
rotate.z = 0; | |
// カメラの X 軸方向の回転角が | |
// -1 ではなく 359 で管理されることがあるため調整しています | |
if ( 180 <= rotate.x ) rotate.x -= 360; | |
rotate.x = Mathf.Clamp( rotate.x, m_minRotateX, m_maxRotateX ); | |
m_cameraAxis.transform.localRotation = Quaternion.Euler( rotate ); | |
} | |
/// <summary> | |
/// スワイプを終了した時に呼び出されます | |
/// </summary> | |
private void On_SwipeEnd( Gesture gesture ) | |
{ | |
RemoveState( State.ROTATE ); | |
} | |
/// <summary> | |
/// ピンチイン中に呼び出されます | |
/// </summary> | |
private void On_PinchIn( Gesture gesture ) | |
{ | |
AddState( State.ZOOM_IN ); | |
CallWaitForEndOfFrame( () => RemoveState( State.ZOOM_IN ) ); | |
Zoom( gesture.deltaPinch ); | |
} | |
/// <summary> | |
/// ピンチアウト中に呼び出されます | |
/// </summary> | |
private void On_PinchOut( Gesture gesture ) | |
{ | |
AddState( State.ZOOM_OUT ); | |
CallWaitForEndOfFrame( () => RemoveState( State.ZOOM_OUT ) ); | |
Zoom( -gesture.deltaPinch ); | |
} | |
/// <summary> | |
/// ズームします | |
/// </summary> | |
private void Zoom( float deltaPinch ) | |
{ | |
var delta = deltaTime * deltaPinch * m_zoomSpeed; | |
var fieldOfView = m_camera.fieldOfView + delta; | |
m_camera.fieldOfView = Mathf.Clamp( fieldOfView, m_minFieldOfView, m_maxFieldOfView ); | |
} | |
/// <summary> | |
/// ステートを追加します | |
/// </summary> | |
private void AddState( State state ) | |
{ | |
m_state |= state; | |
} | |
/// <summary> | |
/// ステートを削除します | |
/// </summary> | |
private void RemoveState( State state ) | |
{ | |
m_state &= ~state; | |
} | |
#if UNITY_EDITOR | |
/// <summary> | |
/// 更新する時に呼び出されます | |
/// </summary> | |
private void Update() | |
{ | |
Zoom( Input.GetAxis( "Mouse ScrollWheel" ) * m_wheelSpeed ); | |
if ( !Input.GetMouseButton( 2 ) ) return; | |
var deltaPosition = new Vector2 | |
( | |
Input.GetAxis( "Mouse X" ), | |
Input.GetAxis( "Mouse Y" ) | |
); | |
Move( deltaPosition * m_mouseSpeed ); | |
} | |
#endif | |
/// <summary> | |
/// 縦持ちの場合 true を設定します | |
/// </summary> | |
public void SetIsPortrait( bool isPortrait ) | |
{ | |
m_isPortrait = isPortrait; | |
var angle = m_camera.transform.localEulerAngles; | |
angle.z = m_isPortrait ? -90 : 0; | |
m_camera.transform.localEulerAngles = angle; | |
} | |
/// <summary> | |
/// カメラのトランスフォームをリセットします | |
/// </summary> | |
public void ResetTranmsform() | |
{ | |
m_cameraAxis.transform.localPosition = m_defaultCameraAxisPos ; | |
m_cameraAxis.transform.localEulerAngles = m_defaultCameraAxisRotate ; | |
var cameraTrans = m_camera.transform; | |
var pos = cameraTrans.localPosition; | |
pos.x = m_defaultCameraPos.x; | |
pos.y = m_defaultCameraPos.y; | |
cameraTrans.localPosition = pos; | |
// カメラの Z 軸方向の回転角は | |
// 縦持ち、横持ちの制御で使用する想定なのでリセットしません | |
var angle = cameraTrans.localEulerAngles; | |
angle.x = m_defaultCameraRotate.x; | |
angle.y = m_defaultCameraRotate.y; | |
cameraTrans.localEulerAngles = angle; | |
m_camera.fieldOfView = m_defaultFieldOfView; | |
} | |
/// <summary> | |
/// 指定されたコールバック関数を 1 フレーム後に呼び出します | |
/// </summary> | |
private void CallWaitForEndOfFrame( Action callback ) | |
{ | |
StartCoroutine( DoCallWaitForEndOfFrame( callback ) ); | |
} | |
/// <summary> | |
/// 指定されたコールバック関数を 1 フレーム後に呼び出すコルーチン | |
/// </summary> | |
private IEnumerator DoCallWaitForEndOfFrame( Action callback ) | |
{ | |
yield return 0; | |
callback(); | |
} | |
/// <summary> | |
/// 指定された列挙型が指定されたフラグを保持している場合 true を返します | |
/// </summary> | |
private static bool HasFlag( Enum self, Enum flag ) | |
{ | |
if ( self.GetType() != flag.GetType() ) return false; | |
var selfValue = Convert.ToUInt64( self ); | |
var flagValue = Convert.ToUInt64( flag ); | |
return ( selfValue & flagValue ) == flagValue; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment