SDHK_Tool.Component.SC_TouchTransform 触摸位置计算器

 

* 作者:闪电Y黑客

* 日期: 2019.7.22

* 功能:计算出触摸拖拽后的位置

 


using SDHK_Tool.Static;
using UnityEngine;
using UnityEngine.EventSystems;

/*
 * 作者:闪电Y黑客
 * 
 * 日期: 2019.7.22
 * 
 * 功能:计算出触摸拖拽后的位置
 *
 */
namespace SDHK_Tool.Component
{

    /// <summary>
    /// 触摸位置计算器
    /// </summary>
    public class SC_TouchTransform : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler, IScrollHandler
    {

        /// <summary>
        /// 电机接口(当电机不为空时,数值将会通过电机计算后再作用到物体上)
        /// </summary>
        private SI_TouchMotor TouchMotor;//电机接口


        /// <summary>
        /// 点击触摸池
        /// </summary>
        [Tooltip("触摸池")]
        public SC_TouchPool_Down TouchPool_Down;

        [Space()]
        [Space()]

        /// <summary>
        /// 忽略鼠标事件
        /// </summary>
        [Tooltip("忽略鼠标")]
        public bool IgnoreMouse = false;

        /// <summary>
        /// 触摸优先:优先使用最新的触摸点进行计算
        /// </summary>
        [Tooltip("触摸优先级")]
        public bool TouchPriority = false;

        /// <summary>
        /// 计算结果直接作用于物体
        /// </summary>
        [Tooltip("拖拽结果作用于物体")]
        public bool UseResults = true;

        [Space()]
        [Space()]

        /// <summary>
        /// 启用移动
        /// </summary>
        [Tooltip("移动")]
        public bool Mobile = true;
        /// <summary>
        /// 启用旋转 
        /// </summary>
        [Tooltip("旋转")]
        public bool Rotation = true;
        /// <summary>
        /// 开启缩放
        /// </summary>
        [Tooltip("缩放")]
        public bool Zoom = true;

        [Space()]
        [Space()]

        /// <summary>
        /// 触摸点数量限制
        /// </summary>
        [Tooltip("触摸点限制")]
        public Vector2 TouchLimit = new Vector2(1, 10);

        [Space()]
        [Space()]

        [Tooltip("调试触摸画线")]
        public bool DebugLine = false;


        //第一第二触摸位置

        /// <summary>
        /// 从点击池筛选出的第一个触摸点
        /// </summary>
        [System.NonSerialized]
        public Vector2 Touch_First;
        /// <summary>
        /// 从点击池筛选出的第二个触摸点,移动禁止情况下为物体的中心点
        /// </summary>
        [System.NonSerialized]
        public Vector2 Touch_Second;


        //触摸拖拽刷新位置

        /// <summary>
        /// 拖拽时计算出的双指中心点
        /// </summary>
        [System.NonSerialized]
        public Vector2 TouchCenterPointer;

        /// <summary>
        /// 拖拽时计算出的双指向量在世界坐标的角度
        /// </summary>
        [System.NonSerialized]
        public float TouchAngle;

        /// <summary>
        /// 拖拽时计算出的双指向量缩放比例差值
        /// </summary>
        [System.NonSerialized]
        public float TouchScale;

        //触摸点之间的向量  

        /// <summary>
        /// 双指向量
        /// </summary>
        [System.NonSerialized]
        public Vector2 FirstToSecond;
        private Vector2 FirstToSecond_Last;


        //初始点击位置存档

        /// <summary>
        /// 每次点击时保存的双指中心点
        /// </summary>
        [System.NonSerialized]
        public Vector2 Save_TouchCenterPointer;

        /// <summary>
        /// 每次点击时保存的双指向量角度
        /// </summary>
        [System.NonSerialized]
        public float Save_TouchAngle;

        /// <summary>
        /// 每次点击时保存的双指向量长度
        /// </summary>
        [System.NonSerialized]
        public float Save_TouchScale;


        //初始点击偏差存档

        /// <summary>
        /// 每次点击时保存的双指中心点到物体中心的距离
        /// </summary>
        [System.NonSerialized]
        public Vector2 Save_TouchCenterToTransform_Position;

        /// <summary>
        /// 每次点击时保存的双指角度与物体z轴的角度差
        /// </summary>
        [System.NonSerialized]
        public float Save_TouchToTransform_Angle;
        // private float Save_TouchToTransform_Scale;


        //计算后的位置

        /// <summary>
        /// 计算拖拽后得到的位置
        /// </summary>
        [System.NonSerialized]
        public Vector2 Transform_Position;

        /// <summary>
        /// 计算拖拽后得到的角度
        /// </summary>
        [System.NonSerialized]
        public float Transform_Angle;

        /// <summary>
        /// 计算拖拽后得到的尺寸
        /// </summary>
        [System.NonSerialized]
        public Vector3 Transform_Scale;



        void Start()
        {

            TouchPool_Down //触摸池是必须要有的
            = (GetComponent<SC_TouchPool_Down>() != null)
            ? GetComponent<SC_TouchPool_Down>()
            : gameObject.AddComponent<SC_TouchPool_Down>()
            ;

            Transform_Position = transform.position;
            Transform_Angle = transform.eulerAngles.z;
            Transform_Scale = transform.lossyScale;

        }

        /// <summary>
        /// 设置电机
        /// </summary>
        /// <param name="TouchMotor">电机</param>
        public void Set_TouchMotor(SI_TouchMotor TouchMotor)
        {
            this.TouchMotor = TouchMotor;
        }


        public void OnPointerDown(PointerEventData eventData)//点击事件
        {
            if (IgnoreMouse && eventData.pointerId < 0) return;//忽略鼠标

            if (TouchPool_Down.TouchPool.Count < TouchLimit.x || TouchPool_Down.TouchPool.Count > TouchLimit.y) return;//触摸限制

            TouchScreening();//稳定点筛选

            FirstToSecond = Touch_Second - Touch_First; //当前手势向量
            FirstToSecond_Last = FirstToSecond;         //上一次的手势向量

            //===================================

            TouchCenterPointer = Touch_First + FirstToSecond * 0.5f;    //当前手势中心点位置
            Save_TouchCenterPointer = TouchCenterPointer;               //手势中心位置存档

            //当前手势向量角度 = 角度计算类.角度转换正负无限数值转换为正360度角(角度计算类.获得两个二维向量的角度差(二维向量.上,当前手势的向量,轴方向翻转));
            TouchAngle = SS_EulerAngleConversion.Angle_PN_To_P360(SS_EulerAngleConversion.Get_Angle_In_Vector2Deviation(Vector2.up, FirstToSecond, false));

            Save_TouchAngle = TouchAngle;   //手势初始角度存档

            Save_TouchScale = FirstToSecond.magnitude;  //手势向量长度存档

            Transform_Scale = transform.lossyScale;     //缩放位置赋值

            //触摸中心到本物体的向量存档 = 真实位置- 触摸中心位置存档;
            Save_TouchCenterToTransform_Position = (Vector2)transform.position - Save_TouchCenterPointer;

            //手势向量角度与本物体角度差值存档 = 数学类.计算角度差(触摸向量角度存档,物体真实角度);
            Save_TouchToTransform_Angle = Mathf.DeltaAngle(Save_TouchAngle, transform.eulerAngles.z);

        }

        public void OnDrag(PointerEventData eventData)//拖拽事件
        {
            if (IgnoreMouse && eventData.pointerId < 0) return;//忽略鼠标

            if (TouchPool_Down.TouchPool.Count < TouchLimit.x || TouchPool_Down.TouchPool.Count > TouchLimit.y) return;//触摸限制

            TouchScreening();//稳定点筛选

            FirstToSecond = Touch_Second - Touch_First;//手势向量计算

            //===================================

            TouchCenterPointer = Touch_First + FirstToSecond * 0.5f;//手势中心点位置

            //当前手势向量角度 = 角度计算类.角度转换正负无限数值转换为正360度角(角度计算类.获得两个二维向量的角度差(二维向量.上,当前手势的向量,轴方向翻转));
            TouchAngle = SS_EulerAngleConversion.Angle_PN_To_P360(SS_EulerAngleConversion.Get_Angle_In_Vector2Deviation(Vector2.up, FirstToSecond, false));

            //缩放后的大小
            if ((Zoom && !Mobile) || (Zoom && TouchPool_Down.TouchPool.Count > 1))
            {
                //缩放比例差值 = ((当前手势向量长度-上一次手势向量长度)/上一次手势向量长度)
                TouchScale = ((FirstToSecond.magnitude - FirstToSecond_Last.magnitude) / FirstToSecond_Last.magnitude);

                //缩放后的虚拟计算大小 += 缩放比例差值 * 当前虚拟大小;
                Transform_Scale += TouchScale * Transform_Scale;

                //缩放后的 触摸点到物体中心向量的存档 += 缩放比例差值 * 触摸点到物体中心向量的存档
                if (Mobile) Save_TouchCenterToTransform_Position += TouchScale * Save_TouchCenterToTransform_Position;
            }

            //移动后的虚拟计算位置 = 触摸中心点 + 触摸中心点到物体中心向量存档;
            if (Mobile) Transform_Position = TouchCenterPointer + Save_TouchCenterToTransform_Position;

            //旋转后的虚拟计算位置 = 角度计算类.获取_位置_环绕旋转(环绕物:虚拟计算位置,环绕中心点:当前触摸手势中心点,轴向:世界坐标.z轴 ,旋转角度:数学类.获取角度差(手势角度存档,当前手势角度));
            if (Mobile && Rotation) Transform_Position = SS_EulerAngleConversion.Get_Vector3_RotateRound(Transform_Position, TouchCenterPointer, Vector3.forward, Mathf.DeltaAngle(Save_TouchAngle, TouchAngle));

            //物体旋转后的虚拟计算角度 = 手势角度与物体角度差存档 + 当前手势角度
            if (Rotation) Transform_Angle = Save_TouchToTransform_Angle + TouchAngle;


            //更新双指的向量值
            FirstToSecond_Last = FirstToSecond;

        }

        public void OnPointerUp(PointerEventData eventData)//抬起事件
        {
            if (IgnoreMouse && eventData.pointerId < 0) return;//忽略鼠标

            if (TouchPool_Down.TouchPool.Count < TouchLimit.x || TouchPool_Down.TouchPool.Count > TouchLimit.y) return;//触摸限制

            TouchScreening();//稳定点筛选

            FirstToSecond = Touch_Second - Touch_First; //当前手势向量
            FirstToSecond_Last = FirstToSecond;         //上一次的手势向量

            //===================================

            TouchCenterPointer = Touch_First + FirstToSecond * 0.5f;    //当前手势中心点位置
            Save_TouchCenterPointer = TouchCenterPointer;               //手势中心位置存档

            //当前手势向量角度 = 角度计算类.角度转换正负无限数值转换为正360度角(角度计算类.获得两个二维向量的角度差(二维向量.上,当前手势的向量,轴方向翻转));
            TouchAngle = SS_EulerAngleConversion.Angle_PN_To_P360(SS_EulerAngleConversion.Get_Angle_In_Vector2Deviation(Vector2.up, FirstToSecond, false));

            Save_TouchAngle = TouchAngle;   //手势初始角度存档

            Save_TouchScale = FirstToSecond.magnitude;  //手势向量长度存档

            //触摸中心到本物体的向量存档 =虚拟计算位置 - 触摸中心位置存档;
            Save_TouchCenterToTransform_Position = Transform_Position - Save_TouchCenterPointer;

            //手势向量角度与本物体角度差值存档 = 数学类.计算角度差(触摸向量角度存档,虚拟计算角度);
            Save_TouchToTransform_Angle = Mathf.DeltaAngle(Save_TouchAngle, Transform_Angle);

        }

        public void OnScroll(PointerEventData eventData)//鼠标滚动
        {
            if (IgnoreMouse && eventData.pointerId < 0) return;//忽略鼠标

            Transform_Scale = transform.lossyScale;     //缩放位置赋值

            //缩放比例差值 = ((当前手势向量长度-上一次手势向量长度)/上一次手势向量长度);
            TouchScale = eventData.scrollDelta.y * 0.1f;

            //缩放后的虚拟计算大小 +=缩放比例差值*当前虚拟大小;
            Transform_Scale += TouchScale * Transform_Scale;

            //缩放后的 触摸点到物体中心向量的存档 += ((当前手势向量长度-上一次手势向量长度)/上一次手势向量长度)*触摸点到物体中心向量的存档
            if (Mobile) Save_TouchCenterToTransform_Position += eventData.scrollDelta.y * 0.1f * Save_TouchCenterToTransform_Position;

        }




        /// <summary>
        /// 触摸点过滤:过滤计算出两个稳定点进行触摸计算
        /// </summary>
        private void TouchScreening()
        {
            if (TouchPool_Down.TouchPool.Count == 0) return;//忽略鼠标

            if (!Mobile && (Rotation || Zoom)) //移动禁用情况
            {

                Touch_First = (TouchPriority)//触摸优先判断
                ? TouchPool_Down.TouchPool[TouchPool_Down.TouchIds[TouchPool_Down.TouchIds.Count - 1]].position//最后一个触摸点
                : Touch_First = TouchPool_Down.TouchPool[TouchPool_Down.TouchIds[0]].position//第一个触摸点
                ;

                Touch_Second = transform.position;              //第二个触摸点为物体中心
            }
            else//开启移动情况
            {
                if (TouchPriority)//触摸优先判断
                {
                    //优先筛选出最新的两个触摸点
                    Touch_First = (TouchPool_Down.TouchPool.Count < 2)
                    ? TouchPool_Down.TouchPool[TouchPool_Down.TouchIds[TouchPool_Down.TouchIds.Count - 1]].position
                    : TouchPool_Down.TouchPool[TouchPool_Down.TouchIds[TouchPool_Down.TouchIds.Count - 2]].position
                    ;
                    Touch_Second = TouchPool_Down.TouchPool[TouchPool_Down.TouchIds[TouchPool_Down.TouchIds.Count - 1]].position;
                }
                else
                {
                    //使用最早的两个触摸点
                    Touch_First = TouchPool_Down.TouchPool[TouchPool_Down.TouchIds[0]].position;
                    Touch_Second = (TouchPool_Down.TouchPool.Count < 2)
                    ? TouchPool_Down.TouchPool[TouchPool_Down.TouchIds[0]].position
                    : TouchPool_Down.TouchPool[TouchPool_Down.TouchIds[1]].position
                    ;
                }
            }


        }


        void Update()
        {

            if (UseResults)//判断是否计算结果直接作用于物体
            {
                if (TouchMotor != null)//判断电机是否存在
                {
                    transform.position = TouchMotor.TouchMortor_Mobile(Transform_Position);
                    transform.eulerAngles = new Vector3(0, 0, TouchMotor.TouchMortor_Rotation(Transform_Angle));
                    transform.localScale = TouchMotor.TouchMortor_Zoom(Transform_Scale);
                }
                else//不存在直接赋值
                {
                    transform.position = Transform_Position;
                    transform.eulerAngles = new Vector3(0, 0, Transform_Angle);
                    transform.localScale = Transform_Scale;
                }

            }


            if (DebugLine)
            {
                Debug.DrawLine(Touch_First, Touch_Second, Color.red);
                Debug.DrawLine(Touch_First, Transform_Position, Color.green);
                Debug.DrawLine(Touch_Second, Transform_Position, Color.green);
                Debug.DrawLine(TouchCenterPointer, Transform_Position, Color.yellow);
            }

        }



    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值