using NextMind.Devices;
using NextMind.Examples.Steps;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace NextMind.Examples.Calibration
{
///
/// This substep and the following are managing this pairing feature like this :
/// 1. Show a first dialogue box display Paired/Connected/Connecting devices AND a "Pair new device" button. The user can else select the device and go directly to the next part, or pair a new device.
/// 2. If the user clicked on "Pair new device", a new dialogue box is shown, asking the user to switch the device in pairing mode.
/// 3. A new dialogue box displays the unpaired available devices. The user must click on the device he wants to pair.
/// 3. When the pairing has been done, another dialogue box prompts the player to confirm the pairing.
/// 4. The last panel just display that all went well.
///
public class DeviceConnectionSubstep : 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;
[SerializeField]
protected Button nextButton = null;
private Dictionary devicesByID;
#region AbstractStep implementation
public override void OnEnterStep()
{
devicesByID = new Dictionary();
InitList();
NeuroManager neuroManager = NeuroManager.Instance;
nextButton.interactable = neuroManager.ConnectedDevices.Count > 0;
ShowLoading(neuroManager.IsScanning);
// Register to the connection events
neuroManager.onDeviceAvailable.AddListener(OnDeviceAvailable);
neuroManager.onDeviceUnavailable.AddListener(OnDeviceUnavailable);
neuroManager.onScanningStarted.AddListener(OnScanningStarted);
neuroManager.onScanningStopped.AddListener(OnScanningStopped);
neuroManager.onDeviceConnected.AddListener(OnDeviceConnected);
}
public override void OnExitStep()
{
Clean();
// Unregister from the connection events
NeuroManager neuroManager = NeuroManager.Instance;
if (neuroManager != null)
{
neuroManager.onDeviceAvailable.RemoveListener(OnDeviceAvailable);
neuroManager.onDeviceUnavailable.RemoveListener(OnDeviceUnavailable);
neuroManager.onScanningStarted.RemoveListener(OnScanningStarted);
neuroManager.onScanningStopped.RemoveListener(OnScanningStopped);
neuroManager.onDeviceConnected.RemoveListener(OnDeviceConnected);
}
}
public override bool GoToNextStepAllowed()
{
// We allow to go to the next step only if a device is connected.
return devicesByID.Count > 0;
}
#endregion
public void OnClickOnPairDevice()
{
deviceConnectionStep.OnStartPairingSteps();
stepsManager.OnClickOnNextStep(true);
}
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)
{
if (!devicesByID.ContainsKey(device.ID))
{
DeviceUIElement uiDevice = Instantiate(deviceUiElementPrefab);
uiDevice.transform.SetParent(availableDevicesListContainer, false);
devicesByID.Add(device.ID, uiDevice);
}
// Init the ui element with conncted device values. If the user click on this device when it is already connected, go to the next step.
devicesByID[device.ID].Init(device, () => { nextButton.onClick.Invoke(); });
}
}
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 your device";
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 OnDeviceConnected(Device device)
{
nextButton.interactable = true;
}
#endregion
#region Scanning events
private void OnScanningStarted()
{
ShowLoading(true);
}
private void OnScanningStopped()
{
ShowLoading(false);
}
#endregion
}
}