using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace NextMind.Devices
{
///
/// This component displays the reliablity of the 's contacts.
///
///
/// It will display contact values as colors on the component of the children objects. To map a contact's to its value, children must have specific names.
/// The following table shows the relation between electrodes names and their id:
///
///
/// Name
/// Id
///
/// - PO80
/// - PO41
///
/// -
/// O22
///
/// -
/// POZ3
///
/// -
/// O14
///
/// -
/// OZ5
///
/// -
/// PO36
///
/// -
/// PO77
///
///
/// If you intend to get the contacts values by yourself, you may want to use the method with these ids as parameter.
///
public class ContactsVisualization : MonoBehaviour
{
///
/// The color to apply on a electrode in a neutral state (e.g. not on the user's head).
///
[SerializeField]
private Color neutralColor = Color.grey;
///
/// The gradient coloring the electrdodes from bad contact to perfect contact.
///
[SerializeField]
private Gradient colorGradient;
///
/// The list of electrodes names.
///
private List electrodesNames = new List { "PO8", "PO4", "O2", "POZ", "O1", "OZ", "PO3", "PO7" };
private List electrodesImage = new List();
///
/// The device currently connected.
///
private Device connectedDevice;
///
/// The last batch of contact values
///
private Dictionary contactValues = new Dictionary();
///
/// One lerp coroutine for each contact.
///
private Coroutine[] colorLerpCoroutines;
///
/// Are we currently updating the contacts?
///
private bool updatingContacts = false;
private void OnEnable()
{
contactValues = new Dictionary();
electrodesImage = new List();
// Get the electrodes Image components from their GameObject name.
for (int i = 0; i < electrodesNames.Count; i++)
{
contactValues.Add(electrodesNames[i], 0);
foreach (Transform t in transform)
{
if (t.name == electrodesNames[i])
{
electrodesImage.Add(t.GetComponent());
break;
}
}
}
colorLerpCoroutines = new Coroutine[electrodesImage.Count];
// Refresh contact 25 times per second.
StartUpdateContactValues(25f);
}
private void OnDisable()
{
updatingContacts = false;
}
private void StartUpdateContactValues(float rate)
{
if (rate == 0)
{
updatingContacts = false;
}
else
{
updatingContacts = true;
StartCoroutine(RefreshContactValues(1f / rate));
}
}
private IEnumerator RefreshContactValues(float rate)
{
while (updatingContacts)
{
if (connectedDevice != null && connectedDevice.IsConnected)
{
for (int i = 0; i < electrodesNames.Count; i++)
{
float contactValue = connectedDevice.GetContact((uint)i) / 100f;
// If the contact value changed.
if (!Mathf.Approximately(contactValues[electrodesNames[i]], contactValue))
{
contactValues[electrodesNames[i]] = contactValue;
if (colorLerpCoroutines[i] == null)
{
Color targetColor;
float value = contactValues[electrodesNames[i]];
if (value < 0 || value > 1)
{
targetColor = neutralColor;
}
else
{
targetColor = colorGradient.Evaluate(value);
}
electrodesImage[i].color = targetColor;
}
}
}
}
else
{
// Retrieve the first connected device.
var connectedDevices = NeuroManager.Instance.ConnectedDevices;
for (int i = 0; i < connectedDevices.Count; i++)
{
Device device = connectedDevices[i];
if (device.IsConnected)
{
connectedDevice = device;
break;
}
}
}
yield return new WaitForSeconds(rate);
}
}
}
}