using System; using System.Collections.Generic; using UnityEngine; using Unity.Mathematics; using static Unity.Mathematics.math; [System.Serializable] public class Cluster : INucleus { // The ScriptableObject asset from which the runtime object has been created public readonly ClusterPrefab prefab; public ClusterPrefab cluster { get; set; } [SerializeField] protected string _name; public virtual string name { get => _name; set => _name = value; } // Hmm, a cluster instance can never be part of a scriptable object...(Cluster) public Cluster(ClusterPrefab parent, ClusterPrefab prefab) { this.prefab = prefab; this.cluster = parent; if (this.cluster != null) this.cluster.nuclei.Add(this); // foreach (IReceptor nucleus in this.prefab.nuclei) { // IReceptor clone = nucleus.CloneTo(null); // this.dynamicNuclei.Add(clone); // } } public virtual IReceptor Clone() { Neuron clone = new(this.cluster, this.name) { array = this.array, }; foreach (Synapse synapse in this.synapses) { Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus); clonedSynapse.weight = synapse.weight; } foreach (INucleus receiver in this.receivers) { clone.AddReceiver(receiver); } return clone; } // Not sure if this belongs here... [SerializeReference] private NucleusArray _array; public NucleusArray array { get { return _array; } set { _array = value; } } #region Synapses // class ClusterSynapse : Synapse { // public IReceptor receptor; // public ClusterSynapse(IReceptor nucleus, INucleus receptor, float weight = 1.0f) : base(nucleus, weight) { // this.receptor = receptor; // } // } [SerializeField] private List _synapses = new(); public List synapses => _synapses; public Synapse AddSynapse(IReceptor sendingNucleus) { Synapse synapse = new(sendingNucleus); //, this.prefab.inputs[0]); this._synapses.Add(synapse); return synapse; // else { // INucleus receptor = (INucleus)this.prefab.nuclei.Find(nucleus => nucleus is INucleus n && nucleus.name == nucleusName); // ClusterSynapse synapse = new(sendingNucleus, receptor); // receptor.AddSynapse(sendingNucleus); // } // // Add synapse to which neuron? // return null; } // Does this even exist already? public void RemoveSynapse() { } #endregion Synapses #region Receivers [SerializeReference] private List _receivers = new(); public List receivers { get { return _receivers; } set { _receivers = value; } } public virtual void AddReceiver(INucleus receivingNucleus) { this._receivers.Add(receivingNucleus); receivingNucleus.AddSynapse(this); } public void RemoveReceiver(INucleus receiverNucleus) { this._receivers.RemoveAll(receiver => receiver == receiverNucleus); receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this); } // public void AddReceiver(INucleus receivingNucleus) { // int newLength = this._receivers.Count + 1; // INucleus[] newReceivers = new INucleus[newLength]; // // Copy the existing receivers // for (int ix = 0; ix < this._receivers.Count; ix++) // newReceivers[ix] = this._receivers[ix]; // // Add the new receivers // newReceivers[this._receivers.Count] = receivingNucleus; // // Replace the receivers with the new receivers // this._receivers = new(newReceivers); // receivingNucleus.AddSynapse(this); // } // public void RemoveReceiver(INucleus receivingNucleus) { // Debug.Log("Clusterinstance. remote receiver"); // int newLength = this._receivers.Count - 1; // if (newLength < 0) // // Array was empty, so we cannot remove anything // return; // INucleus[] newReceivers = new INucleus[newLength]; // int newIx = 0; // // Copy all receivers except receivingNucleus // for (int ix = 0; ix < this._receivers.Count; ix++) { // if (this._receivers[ix] == receivingNucleus) // // skip the receiver we want to remote // continue; // if (newIx >= newLength) // // We want to copy more elements than expected // // the receivingNucleus is not found // // and the original array is returned // return; // newReceivers[newIx] = this._receivers[ix]; // newIx++; // } // this._receivers = new(newReceivers); // } #endregion Receivers #region Runtime [NonSerialized] private int stale = 1000; public bool isSleeping => lengthsq(this.outputValue) == 0; [NonSerialized] protected float3 _outputValue; public virtual float3 outputValue { get { return _outputValue; } set { this.stale = 0; _outputValue = value; } } #region Update public virtual void UpdateState() { UpdateState(new float3(0, 0, 0)); } public void UpdateState(float3 inputValue) { float3 sum = inputValue; // new(0, 0, 0); //Applying the weight factgors foreach (Synapse synapse in this.synapses) { sum += synapse.weight * synapse.nucleus.outputValue; } // This does not work because the prefab nucleus does not have a state this.prefab.inputs[0].UpdateState(sum); } public void UpdateNuclei() { this.stale++; if (this.stale > 2) _outputValue = Vector3.zero; foreach (IReceptor nucleus in this.prefab.nuclei) nucleus.UpdateNuclei(); } #endregion Update #endregion Runtime /* [SerializeField] private List _dynamicNuclei; public List dynamicNuclei {// = new(); get { if (_dynamicNuclei == null) { this._dynamicNuclei = new(); foreach (IReceptor nucleus in this.prefab.nuclei) { IReceptor clone = nucleus.CloneTo(null); this._dynamicNuclei.Add(clone); } } return this._dynamicNuclei; } } public List _inputs = null; public List inputs { get { this._inputs = new(); if (this.dynamicNuclei != null) { foreach (IReceptor receptor in this.dynamicNuclei) { if (receptor is INucleus nucleus) this._inputs.Add(nucleus); } } return this._inputs; } } public INucleus output => this.dynamicNuclei[0] as INucleus; public float3 outputValue => this.output.outputValue; public IReceptor CloneTo(ClusterPrefab parent) { Cluster clone = new(parent, this.prefab); return clone; } public IReceptor Clone() { Cluster clone = new(this.cluster, this.prefab); return clone; } #region Properties public string name { get { return prefab.name; } set { prefab.name = value; } } public bool isSleeping => lengthsq(this.outputValue) == 0; public NucleusArray array { get; set; } #endregion Properties */ }