HTC VIVE UI框架

在开发VR过程中 UI点击用射线检测,改写了SteamVR_LaserPointer类。 目标实现 PointerIn,PointerOut,ClickedDown,Clicking,ClickedUp。 用的是手柄的Trigger

VR UI

SteamVR_LaserPointer 类改写

//======= Copyright (c) Valve Corporation, All rights reserved. ===============
// Made by LCX 
// This FrameWork includes some tools and modules which are used usually. Feel free to contact with us at ant time.Thanks
// QQ: 594721121
using UnityEngine;
using System.Collections;

public struct PointerEventArgs
{
    public uint controllerIndex;
    public uint flags;
    public float distance;
    public Transform target;
}

public delegate void PointerEventHandler(object sender, PointerEventArgs e);

public class SteamVR_LaserPointer : MonoBehaviour
{
    public bool active = true;
    public Color color;
    public float thickness = 0.002f;
    [HideInInspector] public GameObject holder;
    [HideInInspector] public GameObject pointer;
    private bool isActive = false;
    public bool addRigidBody = false;
    public Transform reference;
    public event PointerEventHandler PointerIn;
    public event PointerEventHandler PointerOut;
    public event PointerEventHandler ClickedDown;
    public event PointerEventHandler Clicking;
    public event PointerEventHandler ClickedUp;

    public static SteamVR_LaserPointer Instance;

    public Material LaserMaterial;
    private Transform previousContact = null;
    // Use this for initialization
    private SteamVR_TrackedObject _steamVrTrackedObject;
    #region  初始化

    private void Start()
    {
        Instance = this;
        controller = GetComponent();
        holder = new GameObject();
        holder.transform.parent = this.transform;
        holder.transform.localPosition = Vector3.zero;
        holder.transform.localRotation = Quaternion.identity;
        _steamVrTrackedObject = GetComponent();
        pointer = GameObject.CreatePrimitive(PrimitiveType.Cube);
        pointer.transform.parent = holder.transform;
        pointer.transform.localScale = new Vector3(thickness, thickness, 100f);
        pointer.transform.localPosition = new Vector3(0f, 0f, 50f);
        pointer.transform.localRotation = Quaternion.identity;
        BoxCollider collider = pointer.GetComponent();
        if (addRigidBody)
        {
            if (collider)
            {
                collider.isTrigger = true;
            }
            Rigidbody rigidBody = pointer.AddComponent();
            rigidBody.isKinematic = true;
        }
        else
        {
            if (collider)
            {
                Object.Destroy(collider);
            }
        }
        if (LaserMaterial == null)
        {
            LaserMaterial = new Material(Shader.Find("Unlit/Color"));
            LaserMaterial.SetColor("_Color", color);
        }
        pointer.GetComponent().material = LaserMaterial;
    }

    #endregion

    #region

    public virtual void OnPointerIn(PointerEventArgs e)
    {
        if (PointerIn != null)
            PointerIn(this, e);
        var ui = e.target.GetComponent();
        if (ui != null)
        {
            ui.OnPointIn();
        }
    }

    public virtual void OnPointerOut(PointerEventArgs e)
    {
        if (PointerOut != null)
            PointerOut(this, e);
        var ui = e.target.GetComponent();
        if (ui != null)
        {
            ui.OnPointOut();
        }
    }

    public virtual void OnClickDown(PointerEventArgs e)
    {
        if (ClickedDown != null)
            ClickedDown(this, e);
        var ui = e.target.GetComponent();
        if (ui != null)
        {
            ui.OnClickedDown();
        }
    }

    public virtual void OnClickUp(PointerEventArgs e)
    {
        if (ClickedUp != null)
            ClickedUp(this, e);
        var ui = e.target.GetComponent();
        if (ui != null)
        {
            ui.OnClickedUp();
        }
    }
    public virtual void OnClick(PointerEventArgs e)
    {
        if (Clicking != null)
            Clicking(this, e);
        var ui = e.target.GetComponent();
        if (ui != null)
        {
            ui.OnClicking();
        }
    }
    #endregion

    private SteamVR_TrackedController controller;
    private float dist = 100f;
    private RaycastHit hit;
    // Update is called once per frame
    private void Update()
    {
        var device = SteamVR_Controller.Input((int)_steamVrTrackedObject.index);
        if (!isActive)
        {
            isActive = true;
            this.transform.GetChild(0).gameObject.SetActive(true);
        }
        Ray raycast = new Ray(transform.position, transform.forward);
        bool bHit = Physics.Raycast(raycast, out hit);
        if (previousContact && previousContact != hit.transform)
        {
            PointerEventArgs args = new PointerEventArgs();
            if (controller != null)
            {
                args.controllerIndex = controller.controllerIndex;
            }
            args.distance = 0f;
            args.flags = 0;
            args.target = previousContact;
            OnPointerOut(args);
            previousContact = null;
        }
        if (bHit && previousContact != hit.transform)
        {
            PointerEventArgs argsIn = new PointerEventArgs();
            if (controller != null)
            {
                argsIn.controllerIndex = controller.controllerIndex;
            }
            argsIn.distance = hit.distance;
            argsIn.flags = 0;
            argsIn.target = hit.transform;
            OnPointerIn(argsIn);
            previousContact = hit.transform;
        }

        if (device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger)&& bHit)
        {
            PointerEventArgs argsIn = new PointerEventArgs();
            if (controller != null)
            {
                argsIn.controllerIndex = controller.controllerIndex;
            }
            argsIn.distance = hit.distance;
            argsIn.flags = 0;
            argsIn.target = hit.transform;
            OnClickDown(argsIn);
            previousContact = hit.transform;
        }

        if (device.GetPressUp(SteamVR_Controller.ButtonMask.Trigger) && bHit)
        {
            PointerEventArgs argsIn = new PointerEventArgs();
            if (controller != null)
            {
                argsIn.controllerIndex = controller.controllerIndex;
            }
            argsIn.distance = hit.distance;
            argsIn.flags = 0;
            argsIn.target = hit.transform;
            OnClickUp(argsIn);
            previousContact = hit.transform;
        }
        //TODO 
        if (device.GetPress(SteamVR_Controller.ButtonMask.Trigger) && bHit)
        {
            PointerEventArgs argsIn = new PointerEventArgs();
            if (controller != null)
            {
                argsIn.controllerIndex = controller.controllerIndex;
            }
            argsIn.distance = hit.distance;
            argsIn.flags = 0;
            argsIn.target = hit.transform;
            OnClick(argsIn);
            previousContact = hit.transform;
        }

        if (!bHit)
        {
            previousContact = null;
        }
        if (bHit && hit.distance < 100f)
        {
            dist = hit.distance;
        }

        if (controller != null && controller.triggerPressed)
        {
            pointer.transform.localScale = new Vector3(thickness*5f, thickness*5f, dist);
        }
        else
        {
            pointer.transform.localScale = new Vector3(thickness, thickness, dist);
        }
        pointer.transform.localPosition = new Vector3(0f, 0f, dist/2f);
    }
}

IVRUI 接口

// Made by LCX 
// This FrameWork includes some tools and modules which are used usually. Feel free to contact with us at ant time.Thanks
// QQ: 594721121
public interface IVRUI
{
    void OnPointIn();
    void OnPointOut();
    void OnClickedDown();
    void OnClickedUp();
    void OnClicking();
}

VRUIBase

// Made by LCX 
// This FrameWork includes some tools and modules which are used usually. Feel free to contact with us at ant time.Thanks
// QQ: 594721121

using System;
using UnityEngine;

public abstract class VRUIBase : MonoBehaviour,IVRUI
{
    public event Action OnInUi;
    public event Action OnOutUi;
    public event Action OnTriggerDownUi;
    public event Action OnTriggerUpUi;
    public event Action OnTriggerUi;

    public virtual void OnDestroy()
    {
        OnInUi = null;
        OnOutUi = null;
        OnTriggerDownUi = null;
        OnTriggerUpUi = null;
        OnTriggerUi = null;
    }
    public void OnPointIn()
    {
        if (OnInUi!=null)OnInUi();
    }
    public void OnPointOut()
    {
       if (OnOutUi != null)OnOutUi();
    }

    public void OnClickedDown()
    {
        if (OnTriggerDownUi != null) OnTriggerDownUi();
    }

    public void OnClickedUp()
    {
        if (OnTriggerUpUi != null) OnTriggerUpUi();
    }

    public void OnClicking()
    {
        if (OnTriggerUi != null) OnTriggerUi();
    }
}

UI 元素挂上 VRUIBase 添加collider。 即可调用

你可能感兴趣的:(VRAR)