/* using System.Linq; using System.Collections.Generic; using UnityEngine; #if UNITY_MATHEMATICS using Unity.Mathematics; using static Unity.Mathematics.math; #endif namespace NanoBrain { /// /// Class to manage an array of nuclei for an IReceptor /// /// Would love to get rid of this class. [System.Serializable] public class NucleusArray { /// /// The nuclei in this array /// [SerializeReference] private Nucleus[] _nuclei; public Nucleus[] nuclei { get { return _nuclei; } set { _nuclei = value; } } /// /// Create a new NucleusArray with the given nucleus /// /// The Nucleus to put in the NucleusArray /// This results in an nucleus array of size 1 public NucleusArray(Nucleus nucleus) { this._nuclei = new Nucleus[1]; this._nuclei[0] = nucleus; } /// /// Create a new NucleusArray of the given size /// /// The size of the nucluesArray public NucleusArray(int size) { this._nuclei = new Nucleus[size]; } // public void AddNucleus(ClusterPrefab prefab) { // if (this._nuclei.Length == 0) { // Debug.LogError("Empty perceptoid array, cannot add"); // return; // } // int newLength = this._nuclei.Length + 1; // Nucleus[] newArray = new Nucleus[newLength]; // for (int i = 0; i < this._nuclei.Length; i++) // newArray[i] = this._nuclei[i]; // if (this._nuclei[0] is Nucleus nucleus) { // newArray[newLength - 1] = nucleus.Clone(prefab); // newArray[newLength - 1].name += $": {newLength - 1}"; // } // this._nuclei = newArray; // } // public void RemoveNucleus() { // int newLength = this._nuclei.Length - 1; // if (newLength == 0) { // Debug.LogWarning("Perceptoid array cannot be empty"); // return; // } // Nucleus[] newPerceptei = new Nucleus[newLength]; // for (int i = 0; i < newLength; i++) // newPerceptei[i] = this._nuclei[i]; // // Delete the last perception // if (this._nuclei[newLength] is Nucleus nucleus) // Neuron.Delete(nucleus); //this._nuclei[newLength]); // this._nuclei = newPerceptei; // } public Dictionary thingReceivers = new(); #if UNITY_MATHEMATICS private Nucleus FindReceiver(int thingId, float3 inputValue) { float inputMagnitude = length(inputValue); return FindReceiverMagnitude(thingId, inputMagnitude); } #else private Nucleus FindReceiver(int thingId, Vector3 inputValue) { float inputMagnitude = inputValue.magnitude; return FindReceiverMagnitude(thingId, inputMagnitude); } #endif private Nucleus FindReceiverMagnitude(int thingId, float inputMagnitude) { Neuron selectedReceiver = null; float selectedMagnitude = 0; foreach (Nucleus nucleusReceiver in this._nuclei) { if (nucleusReceiver is not Neuron receiver) continue; if (thingReceivers.ContainsValue(receiver) == false) { // We found an unusued receiver thingReceivers.Add(thingId, receiver); return receiver; } else if (receiver.isSleeping) { // A sleeping receiver is not active and can therefore always be used thingReceivers.Add(thingId, receiver); return receiver; } else if (selectedReceiver == null) { // If we haven't found a receiver yet, just start by taking the first selectedReceiver = receiver; selectedMagnitude = selectedReceiver.outputMagnitude; } // Look for the receiver with the lowest magnitude else { float magnitude = receiver.outputMagnitude; if (magnitude < inputMagnitude && receiver.outputMagnitude < selectedMagnitude) { selectedReceiver = receiver; selectedMagnitude = selectedReceiver.outputMagnitude; } } } if (selectedReceiver != null) { // Replace the receiver // Find the thingId current associated with the receiver int keyToRemove = thingReceivers.FirstOrDefault(r => r.Value.Equals(selectedReceiver)).Key; if (keyToRemove != 0 || thingReceivers.ContainsKey(keyToRemove)) thingReceivers.Remove(keyToRemove); // And add the new association thingReceivers.Add(thingId, selectedReceiver); } return selectedReceiver; } /// /// Process an external stimulus /// /// The value of the stimulus /// The id of the thing causing the stimulus /// The name of the thing causing the stimulus public virtual void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) { CleanupReceivers(); if (this._nuclei[0] is Neuron neuron) inputValue = neuron.Activator(inputValue); if (!thingReceivers.TryGetValue(thingId, out Nucleus selectedReceiver)) { // No existing nucleus for this thing selectedReceiver = FindReceiver(thingId, inputValue); } if (selectedReceiver == null) return; if (thingName != null) { string baseName = selectedReceiver.name; int colonPos = selectedReceiver.name.IndexOf(":"); if (colonPos > 0) baseName = selectedReceiver.name[..colonPos]; selectedReceiver.name = baseName + ": " + thingName; } if (selectedReceiver is Neuron selectedNucleus) selectedNucleus.ProcessStimulusDirect(inputValue); } /// /// Remove a thing-receiver connection when the nucleus is inactive /// private void CleanupReceivers() { List receiversToRemove = new(); foreach (KeyValuePair item in thingReceivers) { if (item.Value != null && item.Value is Neuron neuron && neuron.isSleeping) receiversToRemove.Add(item.Key); } foreach (int thingId in receiversToRemove) { Nucleus selectedReceiver = thingReceivers[thingId]; thingReceivers.Remove(thingId); int colonPos = selectedReceiver.name.IndexOf(":"); if (colonPos > 0) selectedReceiver.name = selectedReceiver.name[..colonPos]; } } } } */