183 lines
5.3 KiB
C#
183 lines
5.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[Serializable]
|
|
public class Nucleus : INucleus {
|
|
|
|
[SerializeField]
|
|
protected string _name;
|
|
public virtual string name {
|
|
get => _name;
|
|
set => _name = value;
|
|
}
|
|
|
|
[SerializeField]
|
|
private List<Synapse> _synapses = new();
|
|
public List<Synapse> synapses => _synapses;
|
|
|
|
[SerializeReference]
|
|
private List<INucleus> _receivers = new();
|
|
public List<INucleus> receivers => _receivers;
|
|
|
|
[SerializeReference]
|
|
private NucleusArray _array;
|
|
public NucleusArray array {
|
|
get { return _array; }
|
|
set { _array = value; }
|
|
}
|
|
|
|
#region Serialization
|
|
|
|
public enum CurvePresets {
|
|
Linear,
|
|
Power,
|
|
Sqrt,
|
|
Reciprocal,
|
|
Custom
|
|
}
|
|
[SerializeField]
|
|
private CurvePresets _curvePreset;
|
|
public CurvePresets curvePreset {
|
|
get { return _curvePreset; }
|
|
set {
|
|
_curvePreset = value;
|
|
this.curve = GenerateCurve();
|
|
}
|
|
}
|
|
public AnimationCurve curve;
|
|
public float curveMax = 1.0f;
|
|
|
|
public AnimationCurve GenerateCurve() {
|
|
switch (this.curvePreset) {
|
|
case CurvePresets.Linear:
|
|
this.curveMax = 1;
|
|
return Synapse.Presets.Linear(1);
|
|
case CurvePresets.Power:
|
|
this.curveMax = 1;
|
|
return Synapse.Presets.Power(2.0f, 1);
|
|
case CurvePresets.Sqrt:
|
|
this.curveMax = 1;
|
|
return Synapse.Presets.Power(0.5f, 1);
|
|
case CurvePresets.Reciprocal:
|
|
this.curveMax = 1 / 0.01f * 1;
|
|
return Synapse.Presets.Reciprocal(1);
|
|
default:
|
|
this.curveMax = 1;
|
|
return this.curve;
|
|
}
|
|
}
|
|
|
|
public virtual void Deserialize(Nucleus nucleus) { }
|
|
|
|
#endregion Serialization
|
|
|
|
#region Runtime state (not serialized)
|
|
|
|
public Cluster cluster { get; set; }
|
|
|
|
private Vector3 _outputValue;
|
|
public Vector3 outputValue {
|
|
get { return _outputValue; }
|
|
set {
|
|
this.stale = 0;
|
|
this._isSleeping = false;
|
|
_outputValue = value;
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
private int stale = 1000;
|
|
|
|
private bool _isSleeping = false;
|
|
public bool isSleeping => _isSleeping;
|
|
|
|
public void UpdateNuclei() {
|
|
this.stale++;
|
|
this._isSleeping = this.stale > 2;
|
|
if (isSleeping)
|
|
_outputValue = Vector3.zero;
|
|
}
|
|
|
|
#endregion Runtime state
|
|
|
|
public Nucleus(string name) {
|
|
this._name = name;
|
|
}
|
|
|
|
public virtual INucleus Clone() {
|
|
Nucleus clone = new(this.name) {
|
|
cluster = this.cluster,
|
|
array = this.array,
|
|
curve = this.curve,
|
|
curvePreset = this.curvePreset,
|
|
curveMax = this.curveMax
|
|
};
|
|
if (clone.cluster != null)
|
|
clone.cluster.nuclei.Add(clone);
|
|
|
|
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;
|
|
}
|
|
|
|
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 static void Delete(INucleus nucleus) {
|
|
foreach (Synapse synapse in nucleus.synapses) {
|
|
if (synapse.nucleus is Nucleus synapse_nucleus) {
|
|
if (synapse_nucleus.receivers.Count > 1) {
|
|
// there is another nucleus feeding into this input nucleus
|
|
synapse_nucleus.receivers.RemoveAll(r => r == nucleus);
|
|
}
|
|
else {
|
|
// No other links, delete it.
|
|
Nucleus.Delete(synapse_nucleus);
|
|
}
|
|
}
|
|
}
|
|
foreach (INucleus receiver in nucleus.receivers) {
|
|
if (receiver != null && receiver.synapses != null)
|
|
receiver.synapses.RemoveAll(s => s.nucleus == nucleus);
|
|
}
|
|
|
|
if (nucleus.cluster != null) {
|
|
nucleus.cluster.nuclei.RemoveAll(n => n == nucleus);
|
|
nucleus.cluster.GarbageCollection();
|
|
}
|
|
}
|
|
|
|
public Synapse AddSynapse(IReceptor sendingNucleus) {
|
|
Synapse synapse = new(sendingNucleus, 1.0f);
|
|
this.synapses.Add(synapse);
|
|
return synapse;
|
|
}
|
|
|
|
public virtual void UpdateState() { }
|
|
|
|
public void UpdateResult(Vector3 result) {
|
|
// float d = Vector3.Distance(result, this.outputValue);
|
|
// if (d < 0.5f) {
|
|
// //Debug.Log($"insignificant update: {d}");
|
|
// return;
|
|
// }
|
|
|
|
this.outputValue = result;
|
|
foreach (INucleus receiver in this.receivers)
|
|
receiver.UpdateState();
|
|
|
|
}
|
|
} |