(十一)自定义VrInputModule

1.前言

本文基于InputModule的逻辑,根据VR的操作特点,写一个VrInputModule。

2.Input

虚拟一个Input类,来获取最基本的信息,如下代码所示(示意代码):

using UnityEngine;
using System.Collections;

public class GazeInput : MonoBehaviour
{
    public Vector2 GetGazePosition()
    {
        return new Vector2(Screen.width/2, Screen.height/2);
    }

    public Vector2 GetGazeDelta()
    {
        //TODO:Get position delta or rotation delta;
        return new Vector2(0, 0);
    }
}

3.自定义InputModule

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class GazeInputModule : BaseInputModule
{
    [SerializeField]
    private float dragThreshold = 10;

    private PointerEventData pointer;

    private GazeInput gaze;

    private GazeInput gazeInput
    {
        get
        {
            if (gaze == null)
            {
                gaze = GetComponent<GazeInput>();
            }

            return gaze;
        }
    }

    private PointerEventData GetGazePointerEventData(out bool pressed,out bool released)
    {
        if (pointer == null)
        {
            pointer = new PointerEventData(eventSystem);
            pointer.dragging = false;
        }

        pressed = PressedThisFrame();
        released = ReleasedThisFrame();

        pointer.position = gazeInput.GetGazePosition();
        pointer.delta = gazeInput.GetGazeDelta();

        eventSystem.RaycastAll(pointer, m_RaycastResultCache);
        pointer.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache);
        m_RaycastResultCache.Clear();

        return pointer;
    }

    private void ProcessGazePress(PointerEventData pointerData, bool pressed, bool released)
    {
        GameObject currentOverGo = pointerData.pointerCurrentRaycast.gameObject;

        if (pressed)
        {
            pointerData.eligibleForClick = true;
            pointer.dragging = false;
            pointerData.pressPosition = pointerData.position;
            pointerData.pointerPressRaycast = pointerData.pointerCurrentRaycast;

            //Selected and deselected event are neglected

            GameObject newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerData, ExecuteEvents.pointerDownHandler);

            if (newPressed == null)
            {
                newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
            }

            pointerData.pointerPress = newPressed;
            pointerData.rawPointerPress = currentOverGo;

            pointerData.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);

            if (pointerData.pointerDrag != null)
            {
                ExecuteEvents.Execute(pointerData.pointerDrag, pointerData, ExecuteEvents.initializePotentialDrag);
            }
        }

        if (released)
        {
            ExecuteEvents.Execute(pointerData.pointerPress, pointerData, ExecuteEvents.pointerUpHandler);

            GameObject pointerClickHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);

            if (pointerData.pointerPress == pointerClickHandler && pointerData.eligibleForClick)
            {
                ExecuteEvents.Execute(pointerData.pointerPress, pointerData, ExecuteEvents.pointerClickHandler);
            }
            else if(pointerData.pointerDrag != null && pointerData.dragging)
            {
                ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerData, ExecuteEvents.dropHandler);
            }

            pointerData.eligibleForClick = false;
            pointerData.pointerPress = null;
            pointerData.rawPointerPress = null;

            if (pointerData.pointerDrag != null && pointerData.dragging)
                ExecuteEvents.Execute(pointerData.pointerDrag, pointerData, ExecuteEvents.endDragHandler);

            pointerData.dragging = false;
            pointerData.pointerDrag = null;

            if (currentOverGo != pointerData.pointerEnter)
            {
                HandlePointerExitAndEnter(pointerData, null);
                HandlePointerExitAndEnter(pointerData, currentOverGo);
            }
        }
    }

    private void ProcessMove(PointerEventData pointerData)
    {
        HandlePointerExitAndEnter(pointerData, pointerData.pointerCurrentRaycast.gameObject);
    }

    private void ProcessDrag(PointerEventData pointerData)
    {
        if (!ShoundProcessDrag(pointerData))
            return;

        if (!pointerData.dragging)
        {
            ExecuteEvents.Execute(pointerData.pointerDrag, pointerData, ExecuteEvents.beginDragHandler);
            pointerData.dragging = true;
        }

        if (pointerData.dragging)
        {
            if (pointerData.pointerPress != pointerData.pointerDrag)
            {
                ExecuteEvents.Execute(pointerData.pointerPress, pointerData, ExecuteEvents.pointerUpHandler);
                pointerData.eligibleForClick = false;
                pointerData.pointerPress = null;
                pointerData.rawPointerPress = null;
            }

            ExecuteEvents.Execute(pointerData.pointerDrag, pointerData, ExecuteEvents.dragHandler);
        }
    }

    public override void Process()
    {
        bool pressed, released;
        PointerEventData eventData = GetGazePointerEventData(out pressed, out released);

        ProcessGazePress(eventData, pressed, released);

        if (!eventData.dragging)
        {
            ProcessMove(eventData);
        }

        if (!released)
        {
            ProcessDrag(eventData);
        }
    }

    private bool PressedThisFrame()
    {
        return Input.GetKeyDown(KeyCode.KeypadEnter);
    }

    private bool ReleasedThisFrame()
    {
        return Input.GetKeyUp(KeyCode.KeypadEnter); ;
    }

    private bool ShoundProcessDrag(PointerEventData pointerData)
    {
        return Mathf.Abs(pointerData.delta.x) > dragThreshold || Mathf.Abs(pointerData.delta.y) > dragThreshold;
    }
}

4.结语

强迫症晚期,没有结语。。。。。。。。

posted @ 2020-04-12 10:57  81192  阅读(393)  评论(0编辑  收藏  举报