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