NucleusArray to Receptor

This commit is contained in:
Pascal Serrarens 2026-02-13 15:12:45 +01:00
parent f295da9c55
commit f8aaa4ca80
8 changed files with 99 additions and 72 deletions

View File

@ -79,13 +79,13 @@ public class Cluster : Nucleus {
// Copy nucleus arrays // Copy nucleus arrays
for (int nucleusIx = 0; nucleusIx < prefabNuclei.Length; nucleusIx++) { for (int nucleusIx = 0; nucleusIx < prefabNuclei.Length; nucleusIx++) {
Nucleus prefabReceptor = prefabNuclei[nucleusIx]; Nucleus prefabReceptor = prefabNuclei[nucleusIx];
if (prefabReceptor is not Nucleus prefabNucleus) if (prefabReceptor is not Receptor prefabNucleus)
continue; continue;
if (prefabNucleus.array == null || prefabNucleus.array.nuclei == null || prefabNucleus.array.nuclei.Length == 0) if (prefabNucleus.array == null || prefabNucleus.array.nuclei == null || prefabNucleus.array.nuclei.Length == 0)
continue; continue;
Nucleus clonedNucleus = clonedNuclei[nucleusIx] as Nucleus; Receptor clonedNucleus = clonedNuclei[nucleusIx] as Receptor;
if (prefabNucleus == prefabNucleus.array.nuclei[0]) { if (prefabNucleus == prefabNucleus.array.nuclei[0]) {
// We clone the array only for the first entry // We clone the array only for the first entry
NucleusArray clonedArray = new(prefabNucleus.array.nuclei.Length, "array"); NucleusArray clonedArray = new(prefabNucleus.array.nuclei.Length, "array");
@ -106,7 +106,7 @@ public class Cluster : Nucleus {
else { else {
// The others will refer to the array created for the first nucleus in the array // The others will refer to the array created for the first nucleus in the array
int firstNucleusIx = GetNucleusIndex(prefabNuclei, prefabNucleus.array.nuclei[0]); int firstNucleusIx = GetNucleusIndex(prefabNuclei, prefabNucleus.array.nuclei[0]);
Nucleus clonedFirstNucleus = clonedNuclei[firstNucleusIx] as Nucleus; Receptor clonedFirstNucleus = clonedNuclei[firstNucleusIx] as Receptor;
clonedNucleus.array = clonedFirstNucleus.array; clonedNucleus.array = clonedFirstNucleus.array;
} }
} }
@ -153,7 +153,7 @@ public class Cluster : Nucleus {
public override Nucleus Clone(ClusterPrefab prefab) { public override Nucleus Clone(ClusterPrefab prefab) {
//Neuron clone = new(this.cluster, this.name) { //Neuron clone = new(this.cluster, this.name) {
Neuron clone = new(prefab, this.name) { Neuron clone = new(prefab, this.name) {
array = this.array, // array = this.array,
}; };
foreach (Synapse synapse in this.synapses) { foreach (Synapse synapse in this.synapses) {

View File

@ -295,15 +295,15 @@ public class ClusterInspector : Editor {
row++; row++;
} }
} }
else { else if (this.currentNucleus is Receptor receptor1) {
float maxValue = 0; float maxValue = 0;
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) { foreach (Nucleus nucleus in receptor1.array.nuclei) {
float value = length(nucleus.outputValue); float value = length(nucleus.outputValue);
if (value > maxValue) if (value > maxValue)
maxValue = value; maxValue = value;
} }
float spacing = 400f / this.currentNucleus.array.nuclei.Count(); float spacing = 400f / receptor1.array.nuclei.Count();
float margin = 10 + spacing / 2; float margin = 10 + spacing / 2;
float xMin = 150 - size; float xMin = 150 - size;
float xMax = 150 + size; float xMax = 150 + size;
@ -318,7 +318,7 @@ public class ClusterInspector : Editor {
Handles.color = Color.black; Handles.color = Color.black;
Handles.DrawAAConvexPolygon(verts); Handles.DrawAAConvexPolygon(verts);
int row = 0; int row = 0;
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) { foreach (Nucleus nucleus in receptor1.array.nuclei) {
Vector3 pos = new(150, margin + row * spacing, 0.0f); Vector3 pos = new(150, margin + row * spacing, 0.0f);
Handles.color = Color.white; Handles.color = Color.white;
// The selected nucleus highlight ring // The selected nucleus highlight ring
@ -357,9 +357,11 @@ public class ClusterInspector : Editor {
int row = 0; int row = 0;
List<NucleusArray> drawnArrays = new(); List<NucleusArray> drawnArrays = new();
foreach (Nucleus receiver in nucleus.receivers) { foreach (Nucleus receiver in nucleus.receivers) {
if (drawnArrays.Contains(receiver.array)) if (receiver is Receptor receptor) {
if (drawnArrays.Contains(receptor.array))
continue; continue;
drawnArrays.Add(receiver.array); drawnArrays.Add(receptor.array);
}
Nucleus receiverNucleus = receiver; Nucleus receiverNucleus = receiver;
if (receiverNucleus == null) if (receiverNucleus == null)
@ -383,10 +385,10 @@ public class ClusterInspector : Editor {
int neuronCount = 0; int neuronCount = 0;
List<NucleusArray> drawnArrays = new(); List<NucleusArray> drawnArrays = new();
foreach (Synapse synapse in nucleus.synapses) { foreach (Synapse synapse in nucleus.synapses) {
if (synapse.nucleus is Neuron neuroid) { if (synapse.nucleus is Receptor receptor) {
if (drawnArrays.Contains(neuroid.array)) if (drawnArrays.Contains(receptor.array))
continue; continue;
drawnArrays.Add(neuroid.array); drawnArrays.Add(receptor.array);
} }
float value = length(synapse.nucleus.outputValue) * synapse.weight; float value = length(synapse.nucleus.outputValue) * synapse.weight;
@ -403,7 +405,7 @@ public class ClusterInspector : Editor {
int row = 0; int row = 0;
drawnArrays = new(); drawnArrays = new();
foreach (Synapse synapse in nucleus.synapses) { foreach (Synapse synapse in nucleus.synapses) {
if (synapse.nucleus is Neuron neuron) { if (synapse.nucleus is Receptor neuron) {
if (drawnArrays.Contains(neuron.array)) if (drawnArrays.Contains(neuron.array))
continue; continue;
drawnArrays.Add(neuron.array); drawnArrays.Add(neuron.array);
@ -461,11 +463,13 @@ public class ClusterInspector : Editor {
fontStyle = FontStyle.Bold, fontStyle = FontStyle.Bold,
}; };
if (nucleus.array == null || nucleus.array.nuclei == null || nucleus.array.nuclei.Count() == 0) if (nucleus is Receptor receptor1) {
nucleus.array = new NucleusArray(nucleus); if (receptor1.array == null || receptor1.array.nuclei == null || receptor1.array.nuclei.Count() == 0)
receptor1.array = new NucleusArray(nucleus);
if ((!expandArray || nucleus.array.nuclei.First() != this.currentNucleus) && nucleus.array.nuclei.Count() > 1) { if ((!expandArray || receptor1.array.nuclei.First() != this.currentNucleus) && receptor1.array.nuclei.Count() > 1) {
Handles.Label(labelPosition, nucleus.array.nuclei.Count().ToString(), style); Handles.Label(labelPosition, receptor1.array.nuclei.Count().ToString(), style);
}
} }
if (nucleus is ReceptorArray receptor) { if (nucleus is ReceptorArray receptor) {
Handles.Label(labelPosition, receptor.instances.Count().ToString(), style); Handles.Label(labelPosition, receptor.instances.Count().ToString(), style);
@ -481,9 +485,9 @@ public class ClusterInspector : Editor {
// Handles.Label(labelPosition, $"[{arrayIx}]", style); // Handles.Label(labelPosition, $"[{arrayIx}]", style);
// } // }
// } // }
if (expandArray && nucleus.array.nuclei.First() == this.currentNucleus) { if (expandArray && nucleus is Receptor receptor2 && receptor2.array.nuclei.First() == this.currentNucleus) {
int arrayIx = 0; int arrayIx = 0;
foreach (Nucleus n in nucleus.array.nuclei) { foreach (Nucleus n in receptor2.array.nuclei) {
if (n == nucleus) if (n == nucleus)
break; break;
arrayIx++; arrayIx++;
@ -672,8 +676,8 @@ public class ClusterInspector : Editor {
continue; continue;
} }
else { else {
if (synapse.nucleus.array != null && synapse.nucleus.array.nuclei.Length > 1) if (synapse.nucleus is Receptor receptor2 && receptor2.array != null && receptor2.array.nuclei.Length > 1)
array = synapse.nucleus.array; array = receptor2.array;
} }
EditorGUILayout.Space(); EditorGUILayout.Space();
@ -721,8 +725,10 @@ public class ClusterInspector : Editor {
neuron.curvePreset = newPreset; neuron.curvePreset = newPreset;
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();
} }
if (neuron.array == null || neuron.array.nuclei == null || neuron.array.nuclei.Count() == 0) if (neuron is Receptor receptor2) {
neuron.array = new NucleusArray(neuron); if (receptor2.array == null || receptor2.array.nuclei == null || receptor2.array.nuclei.Count() == 0)
receptor2.array = new NucleusArray(neuron);
}
// if (this.currentNucleus is Receptor receptor1) { // if (this.currentNucleus is Receptor receptor1) {
// EditorGUILayout.BeginHorizontal(); // EditorGUILayout.BeginHorizontal();
@ -778,15 +784,22 @@ public class ClusterInspector : Editor {
Handles.color = Color.yellow; Handles.color = Color.yellow;
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector); Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
} }
} }
else { else {
foreach (Nucleus nucleus in this.currentNucleus.array.nuclei) { if (this.currentNucleus is Receptor receptor1) {
foreach (Nucleus nucleus in receptor1.array.nuclei) {
Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue); Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue);
Handles.color = Color.yellow; Handles.color = Color.yellow;
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector); Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
} }
} }
else {
Vector3 worldVector = this.gameObject.transform.TransformVector(this.currentNucleus.outputValue);
Handles.color = Color.yellow;
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
}
}
} }
} }

View File

@ -45,12 +45,12 @@ public class Neuron : Nucleus {
public CurvePresets curvePreset { public CurvePresets curvePreset {
get { return _curvePreset; } get { return _curvePreset; }
set { set {
if (this.array != null && this.array.nuclei != null) { // if (this.array != null && this.array.nuclei != null) {
foreach (Neuron nucleus in this.array.nuclei.Cast<Neuron>()) { // foreach (Neuron nucleus in this.array.nuclei.Cast<Neuron>()) {
nucleus._curvePreset = value; // nucleus._curvePreset = value;
nucleus.curve = GenerateCurve(); // nucleus.curve = GenerateCurve();
} // }
} // }
_curvePreset = value; _curvePreset = value;
this.curve = GenerateCurve(); this.curve = GenerateCurve();
} }
@ -145,7 +145,7 @@ public class Neuron : Nucleus {
} }
protected virtual void CloneFields(Neuron clone) { protected virtual void CloneFields(Neuron clone) {
clone.array = this.array; // clone.array = this.array;
clone.bias = this.bias; clone.bias = this.bias;
clone.combinator = this.combinator; clone.combinator = this.combinator;
clone.curve = this.curve; clone.curve = this.curve;

View File

@ -90,35 +90,43 @@ public abstract class Nucleus {
#endregion Receivers #endregion Receivers
[SerializeReference] // [SerializeReference]
private NucleusArray _array; // private NucleusArray _array;
public NucleusArray array { // public NucleusArray array {
get { return _array; } // get { return _array; }
set { _array = value; } // set { _array = value; }
} // }
#region Update #region Update
public abstract void UpdateStateIsolated(); public abstract void UpdateStateIsolated();
public virtual void UpdateNuclei() { public virtual void UpdateNuclei() {
if (this.array == null || this.array.nuclei == null || this.array.nuclei.Length <= 1) // if (this.array == null || this.array.nuclei == null || this.array.nuclei.Length <= 1)
return; return;
this.stale++; // this.stale++;
if (this.stale > staleValueForSleep) { // if (this.stale > staleValueForSleep) {
//Debug.Log($"{this.name} goes to sleep, stale = {this.stale}"); // //Debug.Log($"{this.name} goes to sleep, stale = {this.stale}");
_outputValue = Vector3.zero; // _outputValue = Vector3.zero;
} // }
} }
public virtual void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) { public virtual void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) {
this.array.ProcessStimulus(thingId, inputValue, thingName); //this.array.ProcessStimulus(thingId, inputValue, thingName);
// this.ProcessStimulus(inputValue);
this.stale = 0;
this.bias = inputValue;
this.parent.UpdateFromNucleus(this);
} }
public virtual void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) { // public virtual void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) {
this.array.ProcessStimulus(thingId, inputValue, thingName); // // this.array.ProcessStimulus(thingId, inputValue, thingName);
} // // this.ProcessStimulus(inputValue);
// this.stale = 0;
// this.bias = inputValue;
// this.parent.UpdateFromNucleus(this);
// }
#endregion Update #endregion Update

View File

@ -9,23 +9,26 @@ public class Receptor : Neuron {
public override Nucleus ShallowCloneTo(Cluster parent) { public override Nucleus ShallowCloneTo(Cluster parent) {
Receptor clone = new(parent, name); Receptor clone = new(parent, name);
CloneFields(clone);
clone.array = this.array;
return clone; return clone;
} }
public override Nucleus Clone(ClusterPrefab prefab) { public override Nucleus Clone(ClusterPrefab prefab) {
Receptor clone = new(prefab, name); Receptor clone = new(prefab, name);
CloneFields(clone); CloneFields(clone);
clone.array = this.array;
// Adding receivers will also add synapses to the receivers // Adding receivers will also add synapses to the receivers
foreach (Nucleus receiver in this.receivers) foreach (Nucleus receiver in this.receivers)
clone.AddReceiver(receiver); clone.AddReceiver(receiver);
return clone; return clone;
} }
// [SerializeReference] [SerializeReference]
// private NucleusArray _array; private NucleusArray _array;
// public NucleusArray array { public NucleusArray array {
// get { return _array; } get { return _array; }
// set { _array = value; } set { _array = value; }
// } }
public override void UpdateStateIsolated() { public override void UpdateStateIsolated() {
@ -40,4 +43,7 @@ public class Receptor : Neuron {
} }
} }
public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) {
this.array.ProcessStimulus(thingId, inputValue, thingName);
}
} }

View File

@ -138,9 +138,9 @@ public class ReceptorArray : Nucleus {
private Dictionary<int, Nucleus> thingReceivers = new(); private Dictionary<int, Nucleus> thingReceivers = new();
public override void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) { // public override void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) {
ProcessStimulus(inputValue, thingId, thingName); // ProcessStimulus(inputValue, thingId, thingName);
} // }
public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) { public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) {
CleanupReceivers(); CleanupReceivers();
if (!thingReceivers.TryGetValue(thingId, out Nucleus selectedReceiver)) { if (!thingReceivers.TryGetValue(thingId, out Nucleus selectedReceiver)) {

View File

@ -14,8 +14,8 @@ public class SelectorBrain : NanoBrain {
} }
protected void Update() { protected void Update() {
receptor.ProcessStimulus(0, input1); receptor.ProcessStimulus(input1, 0);
receptor.ProcessStimulus(1, input2); receptor.ProcessStimulus(input2, 1);
output = this.brain.outputValue; output = this.brain.outputValue;
this.brain.UpdateNuclei(); this.brain.UpdateNuclei();

View File

@ -9,7 +9,7 @@ public class Selector : Neuron {
public override Nucleus ShallowCloneTo(Cluster newParent) { public override Nucleus ShallowCloneTo(Cluster newParent) {
Selector clone = new(newParent, this.name) { Selector clone = new(newParent, this.name) {
array = this.array, // array = this.array,
curve = this.curve, curve = this.curve,
curvePreset = this.curvePreset, curvePreset = this.curvePreset,
curveMax = this.curveMax, curveMax = this.curveMax,