using System.Collections.Generic;
using UnityEngine;
namespace NanoBrain {
///
/// The Unity ScriptableObject to implement re-usable Cluster Prefabs
///
[CreateAssetMenu(menuName = "Passer/Cluster")]
public class ClusterPrefab : ScriptableObject {
public Cluster cluster;
/*
/// The nuclei in this cluster
[SerializeReference]
// This list should not include any clusters...
public List nuclei = new();
///
/// The output of this cluster
///
/// This only returens the first(default) nucleus. Use outputs[0] instead
public virtual Nucleus output => this.nuclei[0] as Nucleus;
///
/// The nuclei in this cluster which are meant for receiving signals from outside the cluster
///
/// This is currently the nuclei which do not have any incoming synapse
public List _inputs = null;
public virtual List inputs {
get {
if (this._inputs == null) {
this._inputs = new();
foreach (Nucleus receptor in this.nuclei) {
if (receptor is Nucleus nucleus) {
// inputs have no incoming synapses yet.
if (nucleus.synapses.Count == 0)
this._inputs.Add(nucleus);
}
}
}
return this._inputs;
}
}
///
/// The nuclei in this cluster which are meant for sending signals onward
///
private List _outputs = null;
public List outputs {
get {
if (this._outputs == null)
RefreshOutputs();
return this._outputs;
}
}
///
/// Redetermine the outpus in the cluster
///
public void RefreshOutputs() {
this._outputs = new();
foreach (Nucleus nucleus in this.nuclei) {
if (nucleus is Neuron neuron && neuron.receivers.Count == 0)
this._outputs.Add(nucleus);
}
}
*/
///
/// Retrieve a nucleus in this cluster
///
/// The name of the nucleus
/// The Nucleus with the given name or null if no such Nucleus could be found
public Nucleus GetNucleus(string nucleusName) {
return cluster.GetNucleus(nucleusName);
// foreach (Nucleus nucleus in this.nuclei) {
// if (nucleus.name == nucleusName)
// return nucleus;
// }
// return null;
}
// Call this function to ensure that there is at least one nucleus
// This is an invariant and should be ensured before the nucleus is used
// because output requires it.
public void EnsureInitialization() {
this.cluster.prefab = this;
this.cluster.name = this.name;
this.cluster.nuclei ??= new List();
if (this.cluster.nuclei.Count <= 0)
new Neuron(this.cluster, "Output"); // Every cluster should have at least 1 neuron
this.cluster.instanceCount = 1;
// nuclei ??= new List();
// if (nuclei.Count == 0)
// new Neuron(this, "Output"); // Every cluster should have at least 1 neuron
}
public void GarbageCollection() {
// HashSet visitedNuclei = new();
// foreach (Nucleus output in this.outputs)
// MarkNuclei(visitedNuclei, output);
// //Debug.Log($"Garbage collection found {visitedNuclei.Count} Nuclei");
// this.nuclei.RemoveAll(nucleus => visitedNuclei.Contains(nucleus) == false);
}
// public void MarkNuclei(HashSet visitedNuclei, Nucleus nucleus) {
// if (nucleus is null)
// return;
// if (nucleus.parent != null && nucleus.parent.prefab != this)
// visitedNuclei.Add(nucleus.parent);
// else
// visitedNuclei.Add(nucleus);
// if (nucleus is Neuron neuron) {
// if (neuron.synapses != null) {
// HashSet visitedSynapses = new();
// foreach (Synapse synapse in neuron.synapses) {
// if (synapse != null && synapse.neuron != null) {
// visitedSynapses.Add(synapse);
// if (synapse.neuron is Nucleus synapse_nucleus)
// MarkNuclei(visitedNuclei, synapse_nucleus);
// }
// }
// neuron.synapses.RemoveAll(synapse => visitedSynapses.Contains(synapse) == false);
// }
// if (neuron.receivers != null) {
// HashSet visitedReceivers = new();
// foreach (Nucleus receiver in neuron.receivers) {
// if (receiver != null && receiver != null) {
// visitedReceivers.Add(receiver);
// visitedNuclei.Add(receiver);
// }
// }
// neuron.receivers.RemoveAll(receiver => visitedReceivers.Contains(receiver) == false);
// }
// }
// }
// public virtual void UpdateNuclei() {
// foreach (Nucleus nucleus in this.nuclei)
// nucleus.UpdateNuclei();
// }
// public int GetNucleusIndex(Nucleus receiver) {
// int ix = 0;
// foreach (Nucleus nucleus in this.nuclei) {
// if (receiver == nucleus)
// return ix;
// ix++;
// }
// return -1;
// }
}
}