using NextMind.Core.Event; using NextMind.Devices; using NextMind.Examples.Steps; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace NextMind.Examples.Calibration { /// /// This class displays unpaired available Devices to the user, and prompt the user to select the one to pair. /// public class ChooseDeviceToPairStep : AbstractStep { /// /// Moving part of the scanning feedback. /// [SerializeField] private Image loadingBar = null; /// /// Fixed part of the scanning feedback. /// [SerializeField] private Image loadingBackground = null; /// /// The RectTransform where to instantiate the devices' ui elements. /// [SerializeField] private RectTransform availableDevicesListContainer = null; /// /// The prefab of the UI representation of a Device. /// [SerializeField] private DeviceUIElement deviceUiElementPrefab = null; /// /// The parent step. /// [SerializeField] private DeviceConnectionStep deviceConnectionStep = null; /// /// The text element used to display a message when no device is available. /// [SerializeField] private Text disclaimer = null; private Dictionary devicesByID; #region AbstractStep implementation public override void OnEnterStep() { devicesByID = new Dictionary(); InitList(); NeuroManager neuroManager = NeuroManager.Instance; ShowLoading(neuroManager.IsScanning); // Register to the connection events neuroManager.onDeviceAvailable.AddListener(OnDeviceAvailable); neuroManager.onDeviceUnavailable.AddListener(OnDeviceUnavailable); neuroManager.onScanningStarted.AddListener(OnScanningStarted); neuroManager.onScanningStopped.AddListener(OnScanningStopped); // Listen for devices entering pairing mode neuroManager.onDeviceEvent.AddListener(OnDeviceEventReceived); } public override void OnExitStep() { Clean(); // Unregister from the connection events NeuroManager neuroManager = NeuroManager.Instance; neuroManager.onDeviceAvailable.RemoveListener(OnDeviceAvailable); neuroManager.onDeviceUnavailable.RemoveListener(OnDeviceUnavailable); neuroManager.onScanningStarted.RemoveListener(OnScanningStarted); neuroManager.onScanningStopped.RemoveListener(OnScanningStopped); neuroManager.onDeviceEvent.RemoveListener(OnDeviceEventReceived); } #endregion private void InitList() { var devices = NeuroManager.Instance.Devices; if (devices.Count <= 0) { disclaimer.text = "No device available."; return; } foreach (var device in devices) { AddDevice(device); } } /// /// Instantiate a device UI element in the list. /// /// The Device which has been connected private void AddDevice(Device device) { if (device.ConnectionStatus == ConnectionStatus.Connecting || device.IsConnected || device.Paired) { return; } if (!devicesByID.ContainsKey(device.ID)) { DeviceUIElement uiDevice = Instantiate(deviceUiElementPrefab); uiDevice.transform.SetParent(availableDevicesListContainer, false); devicesByID.Add(device.ID, uiDevice); } // Init the ui element with connected device values. If the user click on this device when it is already connected, go to the next step. devicesByID[device.ID].Init(device, () => { NeuroManager.Instance.ConnectDevice(device, filterPaired: false); }); } private void ShowLoading(bool show) { Color green = loadingBar.color; if (show) { green.a = 0.1f; } loadingBackground.color = green; loadingBar.gameObject.SetActive(show); } private void Clean() { foreach (var element in devicesByID) { Destroy(element.Value.gameObject); } devicesByID.Clear(); } #region Connection events /// /// If a device becomes available, add it to the list. /// /// The device which became available private void OnDeviceAvailable(Device device) { disclaimer.text = "Select the device to pair:"; if (!devicesByID.ContainsKey(device.ID)) { AddDevice(device); } } /// /// If a device becomes unavailable, remove it from the list. /// /// The device which became unavailable private void OnDeviceUnavailable(Device device) { if (!device.IsConnected) { Destroy(devicesByID[device.ID].gameObject); devicesByID.Remove(device.ID); } if (NeuroManager.Instance.Devices.Count <= 0) { disclaimer.text = "No device available."; } } private void OnDeviceEventReceived(int deviceID, EventBase eventBase) { if (eventBase is BLEEvent bleEvent) { if (bleEvent.Value == BLEEvent.Type.PAIRING_CONFIRMATION_REQUESTED) { deviceConnectionStep.OnStartPairingSteps(); stepsManager.OnClickOnNextStep(true); } } } #endregion #region Scanning events private void OnScanningStarted() { ShowLoading(true); } private void OnScanningStopped() { ShowLoading(false); } #endregion } }