//========= 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; namespace HTC.UnityPlugin.Vive.BindingInterface { public class BindingInterfaceRoleSetPanelController : MonoBehaviour { public Type DEFAULT_SELECTED_ROLE = typeof(BodyRole); [Serializable] public class UnityEventSelectRole : UnityEvent { } [Serializable] public class UnityEventString : UnityEvent { } [SerializeField] private Animator m_animator; [SerializeField] private BindingInterfaceRoleSetButtonItem m_roleSetButtonItem; [SerializeField] private BindingInterfaceRoleSetBindingItem m_bindingItem; [SerializeField] private UnityEventSelectRole m_onSelectRoleSet; [SerializeField] private UnityEventString m_onEditBinding; [SerializeField] private UnityEvent m_onFinishEditBinding; private int m_maxBindingCount; private List m_roleSetButtonList = new List(); private int m_selectedRoleIndex = -1; private List m_bindingList = new List(); private string m_editingDevice = string.Empty; private string m_heighLightDevice = string.Empty; private OrderedIndexedSet m_boundDevices = new OrderedIndexedSet(); public ViveRole.IMap selectedRoleMap { get { return m_roleSetButtonList[m_selectedRoleIndex].roleMap; } } public bool isEditing { get { return !string.IsNullOrEmpty(m_editingDevice); } } public bool hasHeightLight { get { return !string.IsNullOrEmpty(m_heighLightDevice); } } private void Awake() { RefreshRoleSelection(); // select the role that have largest binding count for (int i = 0, imax = m_roleSetButtonList.Count; i < imax; ++i) { if (!m_roleSetButtonList[i].roleMap.Handler.BlockBindings && m_roleSetButtonList[i].roleMap.BindingCount == m_maxBindingCount) { SelectRoleSet(i); break; } } } private void OnEnable() { VRModule.onDeviceConnected += OnDeviceConnected; } private void OnDisable() { VRModule.onDeviceConnected -= OnDeviceConnected; FinishEditBinding(); } private void OnDeviceConnected(uint deviceIndex, bool connected) { RefreshSelectedRoleBindings(); } public void SetAnimatorSlideLeft() { if (m_animator.isInitialized) { m_animator.SetTrigger("SlideRoleSetViewLeft"); } } public void SetAnimatorSlideRight() { if (m_animator.isInitialized) { m_animator.SetTrigger("SlideRoleSetViewRight"); } } public void EnableSelection() { for (int i = 0, imax = m_roleSetButtonList.Count; i < imax; ++i) { m_roleSetButtonList[i].interactable = true; } } public void DisableSelection() { for (int i = 0, imax = m_roleSetButtonList.Count; i < imax; ++i) { m_roleSetButtonList[i].interactable = false; } } public void SelectRoleSet(int index) { m_roleSetButtonList[index].SetIsOn(); if (m_selectedRoleIndex == index) { return; } m_selectedRoleIndex = index; m_boundDevices.Clear(); RefreshSelectedRoleBindings(); if (m_onSelectRoleSet != null) { m_onSelectRoleSet.Invoke(selectedRoleMap); } } public void StartEditBinding(string deviceSN) { if (m_editingDevice == deviceSN) { return; } FinishEditBindingNoEvent(); var bindingItemIndex = m_boundDevices.IndexOf(deviceSN); if (bindingItemIndex < 0) { selectedRoleMap.BindDeviceToRoleValue(deviceSN, selectedRoleMap.RoleValueInfo.InvalidRoleValue); m_editingDevice = deviceSN; RefreshSelectedRoleBindings(); RefreshRoleSelection(); } else { m_editingDevice = deviceSN; m_bindingList[m_boundDevices.IndexOf(deviceSN)].isEditing = true; } EnableHeightLightBinding(deviceSN); if (m_onEditBinding != null) { m_onEditBinding.Invoke(m_editingDevice); } } public void FinishEditBindingNoEvent() { if (isEditing) { m_bindingList[m_boundDevices.IndexOf(m_editingDevice)].isEditing = false; } m_editingDevice = string.Empty; } public void FinishEditBinding() { FinishEditBindingNoEvent(); if (m_onFinishEditBinding != null) { m_onFinishEditBinding.Invoke(); } } public void EnableHeightLightBinding(string deviceSN) { if (m_heighLightDevice == deviceSN) { return; } DisableHeightLightBinding(); if (string.IsNullOrEmpty(deviceSN)) { return; } var itemIndex = m_boundDevices.IndexOf(deviceSN); if (itemIndex < 0) { return; } m_heighLightDevice = deviceSN; m_bindingList[itemIndex].isHeighLight = true; } public void DisableHeightLightBinding() { if (hasHeightLight) { m_bindingList[m_boundDevices.IndexOf(m_heighLightDevice)].isHeighLight = false; m_heighLightDevice = string.Empty; } } public void RemoveBinding(string deviceSN) { if (isEditing && m_editingDevice == deviceSN) { FinishEditBinding(); } selectedRoleMap.UnbindDevice(deviceSN); RefreshRoleSelection(); RefreshSelectedRoleBindings(); } public void RefreshRoleSelection() { ViveRole.Initialize(); if (m_roleSetButtonList.Count == 0) { m_roleSetButtonList.Add(m_roleSetButtonItem); m_roleSetButtonItem.index = 0; m_roleSetButtonItem.onSelected += SelectRoleSet; } m_maxBindingCount = 0; var buttonIndex = 0; for (int i = 0, imax = ViveRoleEnum.ValidViveRoleTable.Count; i < imax; ++i) { var roleType = ViveRoleEnum.ValidViveRoleTable.GetValueByIndex(i); var roleMap = ViveRole.GetMap(roleType); if (roleMap.Handler.BlockBindings) { continue; } BindingInterfaceRoleSetButtonItem item; if (buttonIndex >= m_roleSetButtonList.Count) { var itemObj = Instantiate(m_roleSetButtonItem.gameObject); itemObj.transform.SetParent(m_roleSetButtonItem.transform.parent, false); m_roleSetButtonList.Add(item = itemObj.GetComponent()); item.index = buttonIndex; item.onSelected += SelectRoleSet; } else { item = m_roleSetButtonList[buttonIndex]; } m_maxBindingCount = Mathf.Max(m_maxBindingCount, roleMap.BindingCount); item.roleMap = roleMap; ++buttonIndex; } } private IndexedSet m_tempDevices = new OrderedIndexedSet(); public void RefreshSelectedRoleBindings() { var roleMap = m_roleSetButtonList[m_selectedRoleIndex].roleMap; var bindingTable = roleMap.BindingTable; // update bound device list and keep the original order for (int i = 0, imax = m_boundDevices.Count; i < imax; ++i) { m_tempDevices.Add(m_boundDevices[i]); } for (int i = 0, imax = bindingTable.Count; i < imax; ++i) { var boundDevice = bindingTable.GetKeyByIndex(i); if (!m_tempDevices.Remove(boundDevice)) { m_boundDevices.Add(boundDevice); } } for (int i = 0, imax = m_tempDevices.Count; i < imax; ++i) { m_boundDevices.Remove(m_tempDevices[i]); } m_tempDevices.Clear(); if (m_bindingList.Count == 0) { m_bindingList.Add(m_bindingItem); m_bindingItem.onEditPress += StartEditBinding; m_bindingItem.onRemovePress += RemoveBinding; } var bindingIndex = 0; for (int max = m_boundDevices.Count; bindingIndex < max; ++bindingIndex) { BindingInterfaceRoleSetBindingItem item; if (bindingIndex >= m_bindingList.Count) { var itemObj = Instantiate(m_bindingItem.gameObject); itemObj.transform.SetParent(m_bindingItem.transform.parent, false); // set child index to secnd last, last index is for add item itemObj.transform.SetSiblingIndex(itemObj.transform.parent.childCount - 2); m_bindingList.Add(item = itemObj.GetComponent()); item.onEditPress += StartEditBinding; item.onRemovePress += RemoveBinding; } else { item = m_bindingList[bindingIndex]; } item.gameObject.SetActive(true); item.deviceSN = m_boundDevices[bindingIndex]; item.isEditing = isEditing && item.deviceSN == m_editingDevice; item.isHeighLight = hasHeightLight && item.deviceSN == m_heighLightDevice; item.RefreshDisplayInfo(roleMap); } // FIXME: issue in 2017.2.0b2, item won't refresh at the first time, force refresh m_bindingItem.transform.parent.gameObject.SetActive(false); m_bindingItem.transform.parent.gameObject.SetActive(true); for (int max = m_bindingList.Count; bindingIndex < max; ++bindingIndex) { m_bindingList[bindingIndex].gameObject.SetActive(false); } } } }