751 lines
30 KiB
C#
751 lines
30 KiB
C#
//========= Copyright 2016-2023, HTC Corporation. All rights reserved. ===========
|
|
|
|
using HTC.UnityPlugin.Utility;
|
|
using HTC.UnityPlugin.VRModuleManagement;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
namespace HTC.UnityPlugin.Vive
|
|
{
|
|
public static partial class ViveRole
|
|
{
|
|
public struct MappingChangedEventArg
|
|
{
|
|
public int roleValue;
|
|
public uint previousDeviceIndex;
|
|
public uint currentDeviceIndex;
|
|
}
|
|
|
|
public struct MappingChangedEventArg<TRole>
|
|
{
|
|
public TRole role;
|
|
public uint previousDeviceIndex;
|
|
public uint currentDeviceIndex;
|
|
}
|
|
|
|
public interface IMap
|
|
{
|
|
ViveRoleEnum.IInfo RoleValueInfo { get; }
|
|
IMapHandler Handler { get; }
|
|
int BindingCount { get; }
|
|
IIndexedTableReadOnly<string, int> BindingTable { get; }
|
|
|
|
bool IsRoleValueMapped(int roleValue);
|
|
bool IsDeviceMapped(uint deviceIndex);
|
|
uint GetMappedDeviceByRoleValue(int roleValue);
|
|
int GetMappedRoleValueByDevice(uint deviceIndex);
|
|
|
|
[Obsolete("Use BindDeviceToRoleValue instead")]
|
|
void BindRoleValue(int roleValue, string deviceSN);
|
|
void BindDeviceToRoleValue(string deviceSN, int roleValue);
|
|
void BindAll();
|
|
bool UnbindRoleValue(int roleValue); // return true if role is ready for bind
|
|
bool UnbindDevice(string deviceSN); // return true if device is ready for bind
|
|
bool UnbindConnectedDevice(uint deviceIndex); // return true if device is ready for bind
|
|
void UnbindAll();
|
|
|
|
bool IsRoleValueBound(int roleValue);
|
|
bool IsDeviceBound(string deviceSN);
|
|
bool IsDeviceConnectedAndBound(uint deviceIndex);
|
|
string GetBoundDeviceByRoleValue(int roleValue);
|
|
/// <summary>
|
|
/// Should use IsDeviceBound to validate deviceSN before calling this function
|
|
/// </summary>
|
|
int GetBoundRoleValueByDevice(string deviceSN);
|
|
/// <summary>
|
|
/// Should use IsDeviceConnectedAndBound to validate deviceIndex before calling this function
|
|
/// </summary>
|
|
int GetBoundRoleValueByConnectedDevice(uint deviceIndex);
|
|
|
|
event UnityAction<IMap, MappingChangedEventArg> onRoleValueMappingChanged;
|
|
}
|
|
|
|
private sealed class Map : IMap
|
|
{
|
|
private readonly ViveRoleEnum.IInfo m_info;
|
|
private IMapHandler m_handler;
|
|
private bool m_lockInternalMapping;
|
|
|
|
// mapping table
|
|
private readonly uint[] m_role2index;
|
|
private readonly int[] m_index2role;
|
|
|
|
// binding table
|
|
private readonly IndexedSet<uint>[] m_roleBoundDevices; // connected devices only
|
|
private readonly IndexedTable<string, int> m_sn2role;
|
|
|
|
public Map(Type roleType)
|
|
{
|
|
m_info = ViveRoleEnum.GetInfo(roleType);
|
|
|
|
m_role2index = new uint[m_info.ValidRoleLength];
|
|
m_index2role = new int[VRModule.MAX_DEVICE_COUNT];
|
|
|
|
m_roleBoundDevices = new IndexedSet<uint>[m_info.ValidRoleLength];
|
|
m_sn2role = new IndexedTable<string, int>(Mathf.Min(m_info.ValidRoleLength, (int)VRModule.MAX_DEVICE_COUNT));
|
|
|
|
for (int i = 0; i < m_role2index.Length; ++i)
|
|
{
|
|
m_role2index[i] = VRModule.INVALID_DEVICE_INDEX;
|
|
}
|
|
|
|
for (int i = 0; i < m_index2role.Length; ++i)
|
|
{
|
|
m_index2role[i] = m_info.InvalidRoleValue;
|
|
}
|
|
}
|
|
|
|
public ViveRoleEnum.IInfo RoleValueInfo { get { return m_info; } }
|
|
public int BindingCount { get { return m_sn2role.Count; } }
|
|
public IIndexedTableReadOnly<string, int> BindingTable { get { return m_sn2role.ReadOnly; } }
|
|
|
|
public IMapHandler Handler
|
|
{
|
|
get { return m_handler; }
|
|
set
|
|
{
|
|
if (m_handler == value) { return; }
|
|
|
|
if (m_handler != null)
|
|
{
|
|
m_handler.OnDivestedOfCurrentMapHandler();
|
|
m_handler = null;
|
|
}
|
|
|
|
if (value != null)
|
|
{
|
|
if (value.BlockBindings)
|
|
{
|
|
UnbindAll();
|
|
}
|
|
|
|
m_handler = value;
|
|
m_handler.OnAssignedAsCurrentMapHandler();
|
|
}
|
|
}
|
|
}
|
|
|
|
public event UnityAction<IMap, MappingChangedEventArg> onRoleValueMappingChanged;
|
|
|
|
private string DeviceSN(uint deviceIndex) { return VRModule.GetCurrentDeviceState(deviceIndex).serialNumber; }
|
|
|
|
public void OnConnectedDeviceChanged(uint deviceIndex, VRModuleDeviceClass deviceClass, string deviceSN, bool connected)
|
|
{
|
|
if (connected)
|
|
{
|
|
if (IsDeviceBound(deviceSN))
|
|
{
|
|
InternalInsertRoleBoundDevice(deviceSN, deviceIndex, GetBoundRoleValueByDevice(deviceSN));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsDeviceMapped(deviceIndex))
|
|
{
|
|
if (IsDeviceBound(deviceSN))
|
|
{
|
|
InternalRemoveRoleBoundDevice(deviceSN, deviceIndex, GetBoundRoleValueByDevice(deviceSN));
|
|
}
|
|
|
|
if (IsDeviceMapped(deviceIndex))
|
|
{
|
|
InternalUnmapping(GetMappedRoleValueByDevice(deviceIndex), deviceIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_handler != null)
|
|
{
|
|
m_handler.OnConnectedDeviceChanged(deviceIndex, deviceClass, deviceSN, connected);
|
|
}
|
|
}
|
|
|
|
public void OnTrackedDeviceRoleChanged()
|
|
{
|
|
if (m_handler != null)
|
|
{
|
|
m_handler.OnTrackedDeviceRoleChanged();
|
|
}
|
|
}
|
|
|
|
#region retrieve state
|
|
public bool IsRoleValueMapped(int roleValue)
|
|
{
|
|
if (!m_info.IsValidRoleValue(roleValue)) { return false; }
|
|
return IsRoleOffsetMapped(m_info.RoleValueToRoleOffset(roleValue));
|
|
}
|
|
|
|
public bool IsRoleOffsetMapped(int roleOffset)
|
|
{
|
|
return VRModule.IsValidDeviceIndex(m_role2index[roleOffset]);
|
|
}
|
|
|
|
public bool IsDeviceMapped(uint deviceIndex)
|
|
{
|
|
return VRModule.IsValidDeviceIndex(deviceIndex) && m_info.IsValidRoleValue(m_index2role[deviceIndex]);
|
|
}
|
|
|
|
public bool IsRoleValueBound(int roleValue)
|
|
{
|
|
if (!m_info.IsValidRoleValue(roleValue)) { return false; }
|
|
|
|
var roleOffset = m_info.RoleValueToRoleOffset(roleValue);
|
|
return m_roleBoundDevices[roleOffset] != null && m_roleBoundDevices[roleOffset].Count > 0;
|
|
}
|
|
|
|
public bool IsDeviceBound(string deviceSN)
|
|
{
|
|
return string.IsNullOrEmpty(deviceSN) ? false : m_sn2role.ContainsKey(deviceSN);
|
|
}
|
|
|
|
public bool IsDeviceConnectedAndBound(uint deviceIndex)
|
|
{
|
|
return IsDeviceBound(DeviceSN(deviceIndex));
|
|
}
|
|
|
|
public uint GetMappedDeviceByRoleValue(int roleValue)
|
|
{
|
|
if (m_info.IsValidRoleValue(roleValue))
|
|
{
|
|
return m_role2index[m_info.RoleValueToRoleOffset(roleValue)];
|
|
}
|
|
else
|
|
{
|
|
return VRModule.INVALID_DEVICE_INDEX;
|
|
}
|
|
}
|
|
|
|
public int GetMappedRoleValueByDevice(uint deviceIndex)
|
|
{
|
|
if (VRModule.IsValidDeviceIndex(deviceIndex))
|
|
{
|
|
return m_index2role[deviceIndex];
|
|
}
|
|
else
|
|
{
|
|
return m_info.InvalidRoleValue;
|
|
}
|
|
}
|
|
|
|
public string GetBoundDeviceByRoleValue(int roleValue)
|
|
{
|
|
if (!IsRoleValueBound(roleValue)) { return string.Empty; }
|
|
return DeviceSN(GetMappedDeviceByRoleValue(roleValue));
|
|
}
|
|
|
|
public int GetBoundRoleValueByDevice(string deviceSN)
|
|
{
|
|
return m_sn2role[deviceSN];
|
|
}
|
|
|
|
public int GetBoundRoleValueByConnectedDevice(uint deviceIndex)
|
|
{
|
|
return GetBoundRoleValueByDevice(DeviceSN(deviceIndex));
|
|
}
|
|
#endregion retrieve state
|
|
|
|
#region internal operation
|
|
// both roleValue and deviceIndex must be valid
|
|
// ignore binding state
|
|
private void InternalMapping(int roleValue, uint deviceIndex)
|
|
{
|
|
if (m_lockInternalMapping) { throw new Exception("Recursive calling InternalMapping"); }
|
|
m_lockInternalMapping = true;
|
|
|
|
var previousRoleValue = m_index2role[deviceIndex];
|
|
if (roleValue == previousRoleValue)
|
|
{
|
|
m_lockInternalMapping = false;
|
|
return;
|
|
}
|
|
|
|
if (m_info.IsValidRoleValue(previousRoleValue))
|
|
{
|
|
m_lockInternalMapping = false;
|
|
InternalUnmapping(previousRoleValue, deviceIndex);
|
|
m_lockInternalMapping = true;
|
|
}
|
|
|
|
var roleOffset = m_info.RoleValueToRoleOffset(roleValue);
|
|
var previousDeviceIndex = m_role2index[roleOffset];
|
|
var eventArg = new MappingChangedEventArg()
|
|
{
|
|
roleValue = roleValue,
|
|
previousDeviceIndex = previousDeviceIndex,
|
|
currentDeviceIndex = deviceIndex,
|
|
};
|
|
|
|
m_role2index[roleOffset] = deviceIndex;
|
|
m_index2role[deviceIndex] = roleValue;
|
|
|
|
if (VRModule.IsValidDeviceIndex(previousDeviceIndex))
|
|
{
|
|
m_index2role[previousDeviceIndex] = m_info.InvalidRoleValue;
|
|
}
|
|
|
|
if (onRoleValueMappingChanged != null)
|
|
{
|
|
onRoleValueMappingChanged(this, eventArg);
|
|
}
|
|
|
|
m_lockInternalMapping = false;
|
|
}
|
|
|
|
// both roleValue and deviceIndex must be valid
|
|
// ignore binding state
|
|
private void InternalUnmapping(int roleValue, uint deviceIndex)
|
|
{
|
|
if (m_lockInternalMapping) { throw new Exception("Recursive calling InternalMapping"); }
|
|
m_lockInternalMapping = true;
|
|
|
|
var roleOffset = m_info.RoleValueToRoleOffset(roleValue);
|
|
var eventArg = new MappingChangedEventArg()
|
|
{
|
|
roleValue = roleValue,
|
|
previousDeviceIndex = deviceIndex,
|
|
currentDeviceIndex = VRModule.INVALID_DEVICE_INDEX,
|
|
};
|
|
|
|
m_role2index[roleOffset] = VRModule.INVALID_DEVICE_INDEX;
|
|
m_index2role[deviceIndex] = m_info.InvalidRoleValue;
|
|
|
|
if (onRoleValueMappingChanged != null)
|
|
{
|
|
onRoleValueMappingChanged(this, eventArg);
|
|
}
|
|
|
|
m_lockInternalMapping = false;
|
|
}
|
|
|
|
// device must be valid and connected and have bound role value
|
|
// device must not exist in role bound devices
|
|
// boundRoleValue can be whether valid or not
|
|
private void InternalInsertRoleBoundDevice(string deviceSN, uint deviceIndex, int boundRoleValue)
|
|
{
|
|
if (m_info.IsValidRoleValue(boundRoleValue))
|
|
{
|
|
var roleBoundDevices = InternalGetRoleBoundDevices(boundRoleValue);
|
|
|
|
roleBoundDevices.Add(deviceIndex); // if key already added here, means that this device already in role bound devices
|
|
|
|
InternalMapping(boundRoleValue, deviceIndex);
|
|
}
|
|
}
|
|
|
|
// device must be valid and connected and have bound role value
|
|
// device must already exist in role bound devices
|
|
// boundRoleValue can be whether valid or not
|
|
private void InternalRemoveRoleBoundDevice(string deviceSN, uint deviceIndex, int boundRoleValue)
|
|
{
|
|
if (m_info.IsValidRoleValue(boundRoleValue))
|
|
{
|
|
var roleBoundDevices = InternalGetRoleBoundDevices(boundRoleValue);
|
|
|
|
if (!roleBoundDevices.Remove(deviceIndex))
|
|
{
|
|
throw new Exception("device([" + deviceIndex + "]" + deviceSN + ") has not been InternalMappingRoleBoundDevice");
|
|
}
|
|
|
|
if (roleBoundDevices.Count > 0)
|
|
{
|
|
InternalMapping(boundRoleValue, roleBoundDevices[0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// deviceSN must be valid
|
|
// device can be whether bound or not
|
|
// device can be whether connected or not
|
|
private void InternalBind(string deviceSN, int roleValue)
|
|
{
|
|
var deviceIndex = VRModule.GetConnectedDeviceIndex(deviceSN);
|
|
|
|
bool previousIsBound = false;
|
|
int previousBoundRoleValue = m_info.InvalidRoleValue;
|
|
if (m_sn2role.TryGetValue(deviceSN, out previousBoundRoleValue))
|
|
{
|
|
if (previousBoundRoleValue == roleValue) { return; }
|
|
|
|
previousIsBound = true;
|
|
|
|
m_sn2role.Remove(deviceSN);
|
|
|
|
if (VRModule.IsValidDeviceIndex(deviceIndex))
|
|
{
|
|
InternalRemoveRoleBoundDevice(deviceSN, deviceIndex, previousBoundRoleValue);
|
|
}
|
|
}
|
|
|
|
m_sn2role[deviceSN] = roleValue;
|
|
|
|
if (VRModule.IsValidDeviceIndex(deviceIndex))
|
|
{
|
|
InternalInsertRoleBoundDevice(deviceSN, deviceIndex, roleValue);
|
|
}
|
|
|
|
if (m_handler != null)
|
|
{
|
|
m_handler.OnBindingRoleValueChanged(deviceSN, previousIsBound, previousBoundRoleValue, true, roleValue);
|
|
}
|
|
}
|
|
|
|
// deviceSN must be valid
|
|
// device must be bound
|
|
// device can be whether connected or not
|
|
private void InternalUnbind(string deviceSN, int boundRoleValue)
|
|
{
|
|
var deviceIndex = VRModule.GetConnectedDeviceIndex(deviceSN);
|
|
|
|
if (!m_sn2role.Remove(deviceSN))
|
|
{
|
|
throw new Exception("device([" + deviceIndex + "]" + deviceSN + ") already unbound");
|
|
}
|
|
|
|
if (VRModule.IsValidDeviceIndex(deviceIndex))
|
|
{
|
|
InternalRemoveRoleBoundDevice(deviceSN, deviceIndex, boundRoleValue);
|
|
}
|
|
|
|
if (m_handler != null)
|
|
{
|
|
m_handler.OnBindingRoleValueChanged(deviceSN, true, boundRoleValue, false, m_info.InvalidRoleValue);
|
|
}
|
|
}
|
|
#endregion internal operation
|
|
|
|
#region mapping
|
|
public void MappingRoleValue(int roleValue, uint deviceIndex)
|
|
{
|
|
if (!m_info.IsValidRoleValue(roleValue))
|
|
{
|
|
throw new ArgumentException("Cannot mapping invalid roleValue(" + m_info.RoleEnumType.Name + "[" + roleValue + "])");
|
|
}
|
|
|
|
if (!VRModule.IsValidDeviceIndex(deviceIndex))
|
|
{
|
|
throw new ArgumentException("Cannot mapping invalid deviceIndex(" + deviceIndex + ")");
|
|
}
|
|
|
|
if (IsRoleValueBound(roleValue))
|
|
{
|
|
throw new ArgumentException("roleValue(" + m_info.RoleEnumType.Name + "[" + roleValue + "]) is already bound, unbind first.");
|
|
}
|
|
|
|
if (IsDeviceConnectedAndBound(deviceIndex))
|
|
{
|
|
throw new ArgumentException("deviceIndex(" + deviceIndex + ") is already bound, unbind first");
|
|
}
|
|
|
|
InternalMapping(roleValue, deviceIndex);
|
|
}
|
|
|
|
// return true if role is ready for mapping
|
|
public bool UnmappingRoleValue(int roleValue)
|
|
{
|
|
// is mapped?
|
|
if (!IsRoleValueMapped(roleValue)) { return false; }
|
|
|
|
// is bound?
|
|
if (IsRoleValueBound(roleValue)) { return false; }
|
|
|
|
InternalUnmapping(roleValue, GetMappedDeviceByRoleValue(roleValue));
|
|
|
|
return true;
|
|
}
|
|
|
|
// return true if device is ready for mapping
|
|
public bool UnmappingDevice(uint deviceIndex)
|
|
{
|
|
// is mapped?
|
|
if (!IsDeviceMapped(deviceIndex)) { return false; }
|
|
|
|
// is bound?
|
|
if (IsDeviceConnectedAndBound(deviceIndex)) { return false; }
|
|
|
|
InternalUnmapping(GetMappedRoleValueByDevice(deviceIndex), deviceIndex);
|
|
|
|
return true;
|
|
}
|
|
|
|
public void UnmappingAll()
|
|
{
|
|
for (int roleValue = m_info.MinValidRoleValue; roleValue <= m_info.MaxValidRoleValue; ++roleValue)
|
|
{
|
|
if (!m_info.IsValidRoleValue(roleValue)) { continue; }
|
|
|
|
UnmappingRoleValue(roleValue);
|
|
}
|
|
}
|
|
#endregion mapping
|
|
|
|
#region bind
|
|
[Obsolete("Use BindDeviceToRoleValue instead")]
|
|
public void BindRoleValue(int roleValue, string deviceSN)
|
|
{
|
|
BindDeviceToRoleValue(deviceSN, roleValue);
|
|
}
|
|
|
|
public void BindDeviceToRoleValue(string deviceSN, int roleValue)
|
|
{
|
|
if (string.IsNullOrEmpty(deviceSN))
|
|
{
|
|
throw new ArgumentException("deviceSN cannot be null or empty.");
|
|
}
|
|
|
|
if (m_handler != null && m_handler.BlockBindings) { return; }
|
|
|
|
InternalBind(deviceSN, roleValue);
|
|
}
|
|
|
|
// bind all mapped roles & devices
|
|
public void BindAll()
|
|
{
|
|
if (m_handler != null && m_handler.BlockBindings) { return; }
|
|
|
|
for (int roleValue = m_info.MinValidRoleValue; roleValue <= m_info.MaxValidRoleValue; ++roleValue)
|
|
{
|
|
if (!m_info.IsValidRoleValue(roleValue)) { continue; }
|
|
|
|
if (IsRoleValueMapped(roleValue) && !IsRoleValueBound(roleValue))
|
|
{
|
|
InternalBind(DeviceSN(GetMappedDeviceByRoleValue(roleValue)), roleValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool UnbindRoleValue(int roleValue)
|
|
{
|
|
if (!IsRoleValueBound(roleValue)) { return false; }
|
|
|
|
var roleBoundDevices = InternalGetRoleBoundDevices(roleValue);
|
|
var boundDeviceIndex = GetMappedDeviceByRoleValue(roleValue);
|
|
|
|
// unbind other bound device first, to avoid redundent mapping changes event
|
|
while (roleBoundDevices.Count > 1)
|
|
{
|
|
for (int i = roleBoundDevices.Count - 1; i >= 0; --i)
|
|
{
|
|
if (roleBoundDevices[i] != boundDeviceIndex)
|
|
{
|
|
InternalUnbind(DeviceSN(roleBoundDevices[i]), roleValue);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
if (roleBoundDevices.Count == 1)
|
|
{
|
|
InternalUnbind(DeviceSN(boundDeviceIndex), roleValue);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool UnbindDevice(string deviceSN)
|
|
{
|
|
if (!IsDeviceBound(deviceSN)) { return false; }
|
|
|
|
InternalUnbind(deviceSN, GetBoundRoleValueByDevice(deviceSN));
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool UnbindConnectedDevice(uint deviceIndex)
|
|
{
|
|
return UnbindDevice(DeviceSN(deviceIndex));
|
|
}
|
|
|
|
public void UnbindAll()
|
|
{
|
|
for (int i = m_sn2role.Count - 1; i >= 0; --i)
|
|
{
|
|
UnbindDevice(m_sn2role.GetKeyByIndex(i));
|
|
}
|
|
}
|
|
|
|
// roleValue must be valid
|
|
private IndexedSet<uint> InternalGetRoleBoundDevices(int roleValue)
|
|
{
|
|
var roleOffset = m_info.RoleValueToRoleOffset(roleValue);
|
|
|
|
if (m_roleBoundDevices[roleOffset] == null)
|
|
{
|
|
m_roleBoundDevices[roleOffset] = new IndexedSet<uint>();
|
|
}
|
|
|
|
return m_roleBoundDevices[roleOffset];
|
|
}
|
|
#endregion bind
|
|
}
|
|
|
|
public interface IMap<TRole> : IMap
|
|
{
|
|
ViveRoleEnum.IInfo<TRole> RoleInfo { get; }
|
|
|
|
bool IsRoleMapped(TRole role);
|
|
uint GetMappedDeviceByRole(TRole role);
|
|
TRole GetMappedRoleByDevice(uint deviceIndex);
|
|
|
|
[Obsolete("Use BindDeviceToRole instead")]
|
|
void BindRole(TRole role, string deviceSN);
|
|
void BindDeviceToRole(string deviceSN, TRole role);
|
|
bool UnbindRole(TRole role); // return true if role is ready for bind
|
|
|
|
bool IsRoleBound(TRole role);
|
|
string GetBoundDeviceByRole(TRole role);
|
|
TRole GetBoundRoleByDevice(string deviceSN);
|
|
TRole GetBoundRoleByConnectedDevice(uint deviceIndex);
|
|
|
|
event UnityAction<IMap<TRole>, MappingChangedEventArg<TRole>> onRoleMappingChanged;
|
|
}
|
|
|
|
private sealed class GenericMap<TRole> : IMap<TRole>
|
|
{
|
|
public static GenericMap<TRole> s_instance;
|
|
|
|
private readonly ViveRoleEnum.IInfo<TRole> m_info;
|
|
private readonly Map m_map;
|
|
|
|
public GenericMap()
|
|
{
|
|
m_info = ViveRoleEnum.GetInfo<TRole>();
|
|
m_map = GetInternalMap(typeof(TRole));
|
|
|
|
if (s_instance == null)
|
|
{
|
|
s_instance = this;
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("duplicated instance for RoleInfo<" + typeof(TRole).Name + ">");
|
|
}
|
|
|
|
m_map.onRoleValueMappingChanged += OnMappingChanged;
|
|
}
|
|
|
|
public ViveRoleEnum.IInfo RoleValueInfo { get { return m_map.RoleValueInfo; } }
|
|
public ViveRoleEnum.IInfo<TRole> RoleInfo { get { return m_info; } }
|
|
public IMapHandler Handler { get { return m_map.Handler; } }
|
|
public int BindingCount { get { return m_map.BindingCount; } }
|
|
public IIndexedTableReadOnly<string, int> BindingTable { get { return m_map.BindingTable; } }
|
|
|
|
public event UnityAction<IMap, MappingChangedEventArg> onRoleValueMappingChanged { add { m_map.onRoleValueMappingChanged += value; } remove { m_map.onRoleValueMappingChanged -= value; } }
|
|
|
|
public event UnityAction<IMap<TRole>, MappingChangedEventArg<TRole>> onRoleMappingChanged;
|
|
|
|
private void OnMappingChanged(IMap map, MappingChangedEventArg arg)
|
|
{
|
|
if (onRoleMappingChanged != null)
|
|
{
|
|
onRoleMappingChanged(this, new MappingChangedEventArg<TRole>()
|
|
{
|
|
role = m_info.ToRole(arg.roleValue),
|
|
previousDeviceIndex = arg.previousDeviceIndex,
|
|
currentDeviceIndex = arg.currentDeviceIndex,
|
|
});
|
|
}
|
|
}
|
|
|
|
public void MappingRole(TRole role, uint deviceIndex) { m_map.MappingRoleValue(m_info.ToRoleValue(role), deviceIndex); }
|
|
public void MappingRoleValue(int roleValue, uint deviceIndex) { m_map.MappingRoleValue(roleValue, deviceIndex); }
|
|
public bool UnmappingRole(TRole role) { return m_map.UnmappingRoleValue(m_info.ToRoleValue(role)); }
|
|
public bool UnmappingRoleValue(int roleValue) { return m_map.UnmappingRoleValue(roleValue); }
|
|
public bool UnmappingDevice(uint deviceIndex) { return m_map.UnmappingDevice(deviceIndex); }
|
|
public void UnmappingAll() { m_map.UnmappingAll(); }
|
|
|
|
public bool IsRoleMapped(TRole role) { return m_map.IsRoleValueMapped(m_info.ToRoleValue(role)); }
|
|
public bool IsRoleValueMapped(int roleValue) { return m_map.IsRoleValueMapped(roleValue); }
|
|
public bool IsDeviceMapped(uint deviceIndex) { return m_map.IsDeviceMapped(deviceIndex); }
|
|
public uint GetMappedDeviceByRole(TRole role) { return m_map.GetMappedDeviceByRoleValue(m_info.ToRoleValue(role)); }
|
|
public TRole GetMappedRoleByDevice(uint deviceIndex) { return m_info.ToRole(m_map.GetMappedRoleValueByDevice(deviceIndex)); }
|
|
public uint GetMappedDeviceByRoleValue(int roleValue) { return m_map.GetMappedDeviceByRoleValue(roleValue); }
|
|
public int GetMappedRoleValueByDevice(uint deviceIndex) { return m_map.GetMappedRoleValueByDevice(deviceIndex); }
|
|
|
|
[Obsolete("Use BindDeviceToRole instead")]
|
|
public void BindRole(TRole role, string deviceSN) { m_map.BindDeviceToRoleValue(deviceSN, m_info.ToRoleValue(role)); }
|
|
[Obsolete("Use BindDeviceToRoleValue instead")]
|
|
public void BindRoleValue(int roleValue, string deviceSN) { m_map.BindDeviceToRoleValue(deviceSN, roleValue); }
|
|
public void BindDeviceToRole(string deviceSN, TRole role) { m_map.BindDeviceToRoleValue(deviceSN, m_info.ToRoleValue(role)); }
|
|
public void BindDeviceToRoleValue(string deviceSN, int roleValue) { m_map.BindDeviceToRoleValue(deviceSN, roleValue); }
|
|
public void BindAll() { m_map.BindAll(); }
|
|
public bool UnbindRole(TRole role) { return m_map.UnbindRoleValue(m_info.ToRoleValue(role)); }
|
|
public bool UnbindRoleValue(int roleValue) { return m_map.UnbindRoleValue(roleValue); }
|
|
public bool UnbindDevice(string deviceSN) { return m_map.UnbindDevice(deviceSN); }
|
|
public bool UnbindConnectedDevice(uint deviceIndex) { return UnbindConnectedDevice(deviceIndex); }
|
|
public void UnbindAll() { m_map.UnbindAll(); }
|
|
|
|
public bool IsRoleBound(TRole role) { return m_map.IsRoleValueBound(m_info.ToRoleValue(role)); }
|
|
public bool IsRoleValueBound(int roleValue) { return m_map.IsRoleValueBound(roleValue); }
|
|
public bool IsDeviceBound(string deviceSN) { return m_map.IsDeviceBound(deviceSN); }
|
|
public bool IsDeviceConnectedAndBound(uint deviceIndex) { return m_map.IsDeviceConnectedAndBound(deviceIndex); }
|
|
public TRole GetBoundRoleByDevice(string deviceSN) { return m_info.ToRole(m_map.GetBoundRoleValueByDevice(deviceSN)); }
|
|
public TRole GetBoundRoleByConnectedDevice(uint deviceIndex) { return m_info.ToRole(m_map.GetBoundRoleValueByConnectedDevice(deviceIndex)); }
|
|
public string GetBoundDeviceByRole(TRole role) { return m_map.GetBoundDeviceByRoleValue(m_info.ToRoleValue(role)); }
|
|
public string GetBoundDeviceByRoleValue(int roleValue) { return m_map.GetBoundDeviceByRoleValue(roleValue); }
|
|
public int GetBoundRoleValueByDevice(string deviceSN) { return m_map.GetBoundRoleValueByDevice(deviceSN); }
|
|
public int GetBoundRoleValueByConnectedDevice(uint deviceIndex) { return m_map.GetBoundRoleValueByConnectedDevice(deviceIndex); }
|
|
}
|
|
|
|
private static IndexedTable<Type, Map> s_mapTable;
|
|
|
|
private static Map GetInternalMap(Type roleType)
|
|
{
|
|
if (s_mapTable == null)
|
|
{
|
|
s_mapTable = new IndexedTable<Type, Map>();
|
|
}
|
|
|
|
Map map;
|
|
if (!s_mapTable.TryGetValue(roleType, out map))
|
|
{
|
|
var validateResult = ViveRoleEnum.ValidateViveRoleEnum(roleType);
|
|
if (validateResult != ViveRoleEnumValidateResult.Valid)
|
|
{
|
|
Debug.LogWarning(roleType.Name + " is not valid ViveRole type. " + validateResult);
|
|
return null;
|
|
}
|
|
|
|
map = new Map(roleType);
|
|
s_mapTable.Add(roleType, map);
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
public static IMap GetMap(Type roleType)
|
|
{
|
|
return GetInternalMap(roleType);
|
|
}
|
|
|
|
private static GenericMap<TRole> GetInternalMap<TRole>()
|
|
{
|
|
var roleEnumType = typeof(TRole);
|
|
if (GenericMap<TRole>.s_instance == null)
|
|
{
|
|
var validateResult = ViveRoleEnum.ValidateViveRoleEnum(roleEnumType);
|
|
if (validateResult != ViveRoleEnumValidateResult.Valid)
|
|
{
|
|
Debug.LogWarning(roleEnumType.Name + " is not valid ViveRole type. " + validateResult);
|
|
return null;
|
|
}
|
|
|
|
new GenericMap<TRole>();
|
|
}
|
|
|
|
return GenericMap<TRole>.s_instance;
|
|
}
|
|
|
|
public static IMap<TRole> GetMap<TRole>()
|
|
{
|
|
return GetInternalMap<TRole>();
|
|
}
|
|
|
|
public static void AssignMapHandler<TRole>(MapHandler<TRole> mapHandler)
|
|
{
|
|
Initialize();
|
|
GetInternalMap(typeof(TRole)).Handler = mapHandler;
|
|
}
|
|
}
|
|
} |