VR模拟枪支打靶,消灭鬼怪,换弹以及上弦等等硬核枪支操作。 使用HTCVive设备,开启SteamVR进行游玩。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

334 lines
12 KiB

3 years ago
//========= Copyright 2016-2018, HTC Corporation. All rights reserved. ===========
using HTC.UnityPlugin.Utility;
using HTC.UnityPlugin.VRModuleManagement;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace HTC.UnityPlugin.Vive.BindingInterface
{
public class BindingInterfaceDevicePanelController : MonoBehaviour
{
private const float MIN_DEVICE_VIEW_SCALE = 0.01f;
private const float MAX_DEVICE_VIEW_SCALE = 5f;
[Serializable]
public class UnityEventString : UnityEvent<string> { }
[SerializeField]
private Animator m_animator;
[SerializeField]
private InputField m_inputDeviceSN;
[SerializeField]
private Image m_modelIcon;
[SerializeField]
private Button m_buttonCheck;
[SerializeField]
private BindingInterfaceDeviceItem m_deviceItem;
[SerializeField]
private float m_deviceViewMargin = 20f;
[SerializeField]
private bool m_showDebugBoundRect = false;
[SerializeField]
private UnityEventString m_onSelectDevice = new UnityEventString();
[SerializeField]
private UnityEventString m_onMouseEnterDevice = new UnityEventString();
[SerializeField]
private UnityEventString m_onMouseExitDevice = new UnityEventString();
private bool m_initialized;
private bool m_trackingEnabled;
private ViveRole.IMap m_selectedRoleMap;
private RectTransform m_deviceView;
private float m_deviceViewMaskWidth;
private float m_deviceViewMaskHeight;
private IndexedTable<uint, BindingInterfaceDeviceItem> m_itemTable = new IndexedTable<uint, BindingInterfaceDeviceItem>();
private List<BindingInterfaceDeviceItem> m_itemPool = new List<BindingInterfaceDeviceItem>();
private void Initialize()
{
if (m_initialized) { return; }
m_initialized = true;
m_itemPool.Add(m_deviceItem);
m_deviceItem.onClick += m_onSelectDevice.Invoke;
m_deviceItem.onEnter += OnEnterDevice;
m_deviceItem.onExit += OnExitDevice;
m_deviceItem.gameObject.SetActive(false);
m_deviceView = m_deviceItem.transform.parent.GetComponent<RectTransform>();
var deviceViewMaskRect = m_deviceView.parent.GetComponent<RectTransform>().rect;
m_deviceViewMaskWidth = deviceViewMaskRect.width;
m_deviceViewMaskHeight = deviceViewMaskRect.height;
}
public void EnableTracking()
{
if (m_trackingEnabled) { return; }
m_trackingEnabled = true;
Initialize();
m_inputDeviceSN.text = string.Empty;
CheckInputDeviceSN(string.Empty);
for (uint deviceIndex = 0; deviceIndex < VRModule.MAX_DEVICE_COUNT; ++deviceIndex)
{
if (VRModule.GetCurrentDeviceState(deviceIndex).isConnected)
{
OnDeviceConnected(deviceIndex, true);
}
}
VRModule.onDeviceConnected += OnDeviceConnected;
}
public void DisableTracking()
{
if (!m_trackingEnabled) { return; }
m_trackingEnabled = false;
VRModule.onDeviceConnected -= OnDeviceConnected;
for (int i = 0, imax = m_itemTable.Count; i < imax; ++i)
{
var item = m_itemTable.GetValueByIndex(i);
m_itemPool.Add(m_itemTable.GetValueByIndex(i));
item.gameObject.SetActive(false);
}
m_itemTable.Clear();
}
private void OnDisable()
{
DisableTracking();
}
private Vector3[] m_itemCorners = new Vector3[4];
private Image m_bound;
private void Update()
{
if (m_trackingEnabled)
{
var boundRect = new Rect()
{
xMin = float.MaxValue,
xMax = float.MinValue,
yMin = float.MaxValue,
yMax = float.MinValue,
};
if (m_showDebugBoundRect && m_bound == null)
{
var boundObj = new GameObject();
boundObj.transform.SetParent(m_deviceView.transform, false);
boundObj.transform.SetAsFirstSibling();
m_bound = boundObj.AddComponent<Image>();
m_bound.color = new Color(1f, 0f, 0f, 5f);
}
for (int i = 0, imax = m_itemTable.Count; i < imax; ++i)
{
var item = m_itemTable.GetValueByIndex(i);
if (!item.isDisplayed) { continue; }
item.UpdatePosition();
item.rectTransform.GetWorldCorners(m_itemCorners);
for (int j = 0; j < 4; ++j)
{
m_itemCorners[j] = m_deviceView.InverseTransformPoint(m_itemCorners[j]);
}
boundRect.xMin = Mathf.Min(boundRect.xMin, m_itemCorners[0].x, m_itemCorners[1].x, m_itemCorners[2].x, m_itemCorners[3].x);
boundRect.xMax = Mathf.Max(boundRect.xMax, m_itemCorners[0].x, m_itemCorners[1].x, m_itemCorners[2].x, m_itemCorners[3].x);
boundRect.yMin = Mathf.Min(boundRect.yMin, m_itemCorners[0].y, m_itemCorners[1].y, m_itemCorners[2].y, m_itemCorners[3].y);
boundRect.yMax = Mathf.Max(boundRect.yMax, m_itemCorners[0].y, m_itemCorners[1].y, m_itemCorners[2].y, m_itemCorners[3].y);
}
// calculate view panel's scale to let view rect includes all devices
var innerWidth = m_deviceViewMaskWidth - (m_deviceViewMargin * 2f);
var innerHeight = m_deviceViewMaskHeight - (m_deviceViewMargin * 2f);
var maxBoundWidth = Mathf.Max(Mathf.Abs(boundRect.xMin), Mathf.Abs(boundRect.xMax)) * 2f;
var maxBoundHeight = Mathf.Max(Mathf.Abs(boundRect.yMin), Mathf.Abs(boundRect.yMax)) * 2f;
float scale;
if (innerWidth / innerHeight >= maxBoundWidth / maxBoundHeight)
{
// if viewRect is wider then boundRect
scale = innerHeight / maxBoundHeight;
}
else
{
// if boundRect is wider then viewRect
scale = innerWidth / maxBoundWidth;
}
scale = Mathf.Clamp(scale, MIN_DEVICE_VIEW_SCALE, MAX_DEVICE_VIEW_SCALE);
if (m_showDebugBoundRect)
{
m_bound.rectTransform.sizeDelta = new Vector2(boundRect.width, boundRect.height);
m_bound.rectTransform.localPosition = boundRect.center;
}
m_deviceView.localScale = new Vector3(scale, scale, 1f);
}
}
private void OnDeviceConnected(uint deviceIndex, bool connected)
{
BindingInterfaceDeviceItem item;
if (connected)
{
if (m_itemPool.Count == 0)
{
var itemObj = Instantiate(m_deviceItem.gameObject);
itemObj.transform.SetParent(m_deviceItem.transform.parent, false);
item = itemObj.GetComponent<BindingInterfaceDeviceItem>();
item.onClick += m_onSelectDevice.Invoke;
item.onEnter += OnEnterDevice;
item.onExit += OnExitDevice;
}
else
{
item = m_itemPool[m_itemPool.Count - 1];
m_itemPool.RemoveAt(m_itemPool.Count - 1); // remove last
}
m_itemTable.Add(deviceIndex, item);
item.deviceIndex = deviceIndex;
item.isBound = m_selectedRoleMap.IsDeviceConnectedAndBound(deviceIndex);
item.UpdateModel();
}
else
{
item = m_itemTable[deviceIndex];
m_itemTable.Remove(deviceIndex);
m_itemPool.Add(item);
}
item.gameObject.SetActive(connected);
}
private void OnEnterDevice(uint deviceIndex)
{
var deviceState = VRModule.GetCurrentDeviceState(deviceIndex);
var deviceSN = deviceState.serialNumber;
m_inputDeviceSN.text = deviceSN;
CheckInputDeviceSN(deviceSN);
m_modelIcon.gameObject.SetActive(true);
BindingInterfaceSpriteManager.SetupDeviceIcon(m_modelIcon, deviceState.deviceModel, true);
if (m_onMouseEnterDevice != null)
{
m_onMouseEnterDevice.Invoke(deviceSN);
}
}
private void OnExitDevice(uint deviceIndex)
{
var deviceSN = VRModule.GetCurrentDeviceState(deviceIndex).serialNumber;
m_inputDeviceSN.text = string.Empty;
CheckInputDeviceSN(string.Empty);
m_modelIcon.gameObject.SetActive(false);
if (m_onMouseExitDevice != null)
{
m_onMouseExitDevice.Invoke(deviceSN);
}
}
public void CheckInputDeviceSN(string inputStr)
{
if (string.IsNullOrEmpty(inputStr))
{
m_buttonCheck.interactable = false;
m_modelIcon.gameObject.SetActive(false);
}
else
{
m_buttonCheck.interactable = true;
m_modelIcon.gameObject.SetActive(true);
uint deviceIndex;
if (VRModule.TryGetConnectedDeviceIndex(inputStr, out deviceIndex))
{
BindingInterfaceSpriteManager.SetupDeviceIcon(m_modelIcon, VRModule.GetCurrentDeviceState(deviceIndex).deviceModel, true);
}
else
{
BindingInterfaceSpriteManager.SetupDeviceIcon(m_modelIcon, ViveRoleBindingsHelper.GetDeviceModelHint(inputStr), false);
}
}
}
public void UpdateForBindingChanged()
{
for (int i = 0, imax = m_itemTable.Count; i < imax; ++i)
{
var deviceIndex = m_itemTable.GetKeyByIndex(i);
var item = m_itemTable.GetValueByIndex(i);
item.isBound = m_selectedRoleMap.IsDeviceConnectedAndBound(deviceIndex);
item.UpdateModel();
}
}
public void ConfirmInputDeviceSN()
{
if (m_onSelectDevice != null)
{
m_onSelectDevice.Invoke(m_inputDeviceSN.text);
}
}
public void DeselectCheckButton()
{
EventSystem.current.SetSelectedGameObject(null);
}
public void SelecRoleSet(ViveRole.IMap roleMap)
{
m_selectedRoleMap = roleMap;
}
public void SetAnimatorSlideLeft()
{
if (m_animator.isInitialized)
{
m_animator.SetTrigger("SlideDeviceViewLeft");
}
}
public void SetAnimatorSlideRight()
{
if (m_animator.isInitialized)
{
m_animator.SetTrigger("SlideDeviceViewRight");
}
}
public void SetAnimatorIsEditing(bool value)
{
if (m_animator.isInitialized)
{
m_animator.SetBool("isEditing", value);
}
}
}
}