using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(menuName = "Passer/Cluster")] public class ClusterPrefab : ScriptableObject { // The ScriptableObject asset from which the runtime object has been created public string hello = "hello"; [SerializeReference] public List nuclei = new(); public virtual Nucleus output => this.nuclei[0] as Nucleus; 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; } } private List _outputs = null; public List outputs { get { if (this._outputs == null) RefreshOutputs(); return this._outputs; } } public void RefreshOutputs() { this._outputs = new(); foreach (Nucleus nucleus in this.nuclei) { if (nucleus.receivers.Count == 0) this._outputs.Add(nucleus); } } public Nucleus GetNucleus(string 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() { 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); //MarkNuclei(visitedNuclei, this.output); //Debug.Log($"Garbage collection found {visitedNuclei.Count} Nuclei"); this.nuclei.RemoveAll(nucleus => nucleus is Nucleus n && visitedNuclei.Contains(n) == false); } public void MarkNuclei(HashSet visitedNuclei, Nucleus nucleus) { if (nucleus is null) return; visitedNuclei.Add(nucleus); if (nucleus.synapses != null) { HashSet visitedSynapses = new(); foreach (Synapse synapse in nucleus.synapses) { if (synapse != null && synapse.nucleus != null) { visitedSynapses.Add(synapse); if (synapse.nucleus is Nucleus synapse_nucleus) MarkNuclei(visitedNuclei, synapse_nucleus); } } nucleus.synapses.RemoveAll(synapse => visitedSynapses.Contains(synapse) == false); } if (nucleus.receivers != null) { HashSet visitedReceivers = new(); foreach (Nucleus receiver in nucleus.receivers) { if (receiver != null && receiver != null) { visitedReceivers.Add(receiver); visitedNuclei.Add(receiver); } } nucleus.receivers.RemoveAll(receiver => visitedReceivers.Contains(receiver) == false); } } public virtual void UpdateNuclei() { foreach (Nucleus nucleus in this.nuclei) nucleus.UpdateNuclei(); } }