Step to get rid of NucleusArray

This commit is contained in:
Pascal Serrarens 2026-02-19 12:13:02 +01:00
parent 116a5819e0
commit d2b5d2feac
7 changed files with 116 additions and 44 deletions

View File

@ -84,15 +84,15 @@ public class Cluster : Nucleus {
if (prefabReceptor is not Receptor prefabNucleus)
continue;
if (prefabNucleus.array == null || prefabNucleus.array.nuclei == null || prefabNucleus.array.nuclei.Length == 0)
if (prefabNucleus.nucleiArray == null || prefabNucleus.nucleiArray.Length == 0)
continue;
Receptor clonedNucleus = clonedNuclei[nucleusIx] as Receptor;
if (prefabNucleus == prefabNucleus.array.nuclei[0]) {
if (prefabNucleus == prefabNucleus.nucleiArray[0]) {
// We clone the array only for the first entry
NucleusArray clonedArray = new(prefabNucleus.array.nuclei.Length, "array");
NucleusArray clonedArray = new(prefabNucleus.nucleiArray.Length, "array");
int arrayIx = 0;
foreach (Nucleus prefabArrayNucleus in prefabNucleus.array.nuclei) {
foreach (Nucleus prefabArrayNucleus in prefabNucleus.nucleiArray) {
int arrayNucleusIx = GetNucleusIndex(prefabNuclei, prefabArrayNucleus);
if (arrayNucleusIx >= 0) {
Nucleus clonedArrayNucleus = clonedNuclei[arrayNucleusIx];
@ -107,9 +107,9 @@ public class Cluster : Nucleus {
}
else {
// 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.nucleiArray[0]);
Receptor clonedFirstNucleus = clonedNuclei[firstNucleusIx] as Receptor;
clonedNucleus.array = clonedFirstNucleus.array;
clonedNucleus.nucleiArray = clonedFirstNucleus.nucleiArray;
}
}
}

View File

@ -65,6 +65,21 @@ public class ClusterReceptor : Cluster, IReceptor {
set { _array = value; }
}
//[SerializeReference]
//private Nucleus[] _nucleusArray;
public Nucleus[] nucleiArray {
get { return _array.nuclei; }
set { _array.nuclei = value; }
}
public void AddReceptorElement(ClusterPrefab prefab) {
this.nucleiArray = IReceptorHelpers.AddReceptorElement(this.nucleiArray, prefab);
}
public void RemoveReceptorElement() {
this.nucleiArray = IReceptorHelpers.RemoveReceptorElement(this.nucleiArray);
}
public override void UpdateStateIsolated() {
float3 sum = this.bias;

View File

@ -300,13 +300,13 @@ public class ClusterInspector : Editor {
// else
if (this.currentNucleus is IReceptor receptor1) {
float maxValue = 0;
foreach (Nucleus nucleus in receptor1.array.nuclei) {
foreach (Nucleus nucleus in receptor1.nucleiArray) {
float value = length(nucleus.outputValue);
if (value > maxValue)
maxValue = value;
}
float spacing = 400f / receptor1.array.nuclei.Count();
float spacing = 400f / receptor1.nucleiArray.Count();
float margin = 10 + spacing / 2;
float xMin = 150 - size;
float xMax = 150 + size;
@ -321,7 +321,7 @@ public class ClusterInspector : Editor {
Handles.color = Color.black;
Handles.DrawAAConvexPolygon(verts);
int row = 0;
foreach (Nucleus nucleus in receptor1.array.nuclei) {
foreach (Nucleus nucleus in receptor1.nucleiArray) {
Vector3 pos = new(150, margin + row * spacing, 0.0f);
Handles.color = Color.white;
// The selected nucleus highlight ring
@ -387,12 +387,12 @@ public class ClusterInspector : Editor {
float margin = 10 + spacing / 2;
int row = 0;
List<NucleusArray> drawnArrays = new();
List<Nucleus[]> drawnArrays = new();
foreach (Nucleus receiver in receivers) {
if (receiver is Receptor receptor) {
if (drawnArrays.Contains(receptor.array))
if (drawnArrays.Contains(receptor.nucleiArray))
continue;
drawnArrays.Add(receptor.array);
drawnArrays.Add(receptor.nucleiArray);
}
Nucleus receiverNucleus = receiver;
@ -415,17 +415,17 @@ public class ClusterInspector : Editor {
// This is used to 'scale' the output value colors of the nuclei
float maxValue = 0;
int neuronCount = 0;
List<NucleusArray> drawnArrays = new();
List<Nucleus[]> drawnArrays = new();
foreach (Synapse synapse in nucleus.synapses) {
if (synapse.nucleus is Receptor receptor) {
if (drawnArrays.Contains(receptor.array))
if (drawnArrays.Contains(receptor.nucleiArray))
continue;
drawnArrays.Add(receptor.array);
drawnArrays.Add(receptor.nucleiArray);
}
else if (synapse.nucleus.parent is ClusterReceptor clusterReceptor) {
if (drawnArrays.Contains(clusterReceptor.array))
if (drawnArrays.Contains(clusterReceptor.nucleiArray))
continue;
drawnArrays.Add(clusterReceptor.array);
drawnArrays.Add(clusterReceptor.nucleiArray);
}
float value = length(synapse.nucleus.outputValue) * synapse.weight;
// Debug.Log($"{synapse.nucleus.name}: {value} {length(synapse.nucleus.outputValue)} {synapse.weight}");
@ -442,14 +442,14 @@ public class ClusterInspector : Editor {
drawnArrays = new();
foreach (Synapse synapse in nucleus.synapses) {
if (synapse.nucleus is Receptor neuron) {
if (drawnArrays.Contains(neuron.array))
if (drawnArrays.Contains(neuron.nucleiArray))
continue;
drawnArrays.Add(neuron.array);
drawnArrays.Add(neuron.nucleiArray);
}
else if (synapse.nucleus.parent is ClusterReceptor clusterReceptor) {
if (drawnArrays.Contains(clusterReceptor.array))
if (drawnArrays.Contains(clusterReceptor.nucleiArray))
continue;
drawnArrays.Add(clusterReceptor.array);
drawnArrays.Add(clusterReceptor.nucleiArray);
}
Vector3 pos = new(250, margin + row * spacing, 0.0f);
Handles.color = Color.white;
@ -521,7 +521,7 @@ public class ClusterInspector : Editor {
style.normal.textColor = Color.black;
else
style.normal.textColor = Color.white;
Handles.Label(labelPosition, receptor1.array.nuclei.Length.ToString(), style);
Handles.Label(labelPosition, receptor1.nucleiArray.Length.ToString(), style);
style.normal.textColor = Color.white;
}
}
@ -704,15 +704,17 @@ public class ClusterInspector : Editor {
}
if (this.currentNucleus is Receptor receptor1) {
EditorGUILayout.BeginHorizontal();
EditorGUILayout.IntField("Array size", receptor1.array.nuclei.Count());
EditorGUILayout.IntField("Array size", receptor1.nucleiArray.Count());
if (GUILayout.Button("Add")) {
Undo.RecordObject(prefabAsset, "Array add " + prefabAsset.name);
receptor1.array.AddNucleus(this.prefab);
//receptor1.array.AddNucleus(this.prefab);
receptor1.AddReceptorElement(this.prefab);
anythingChanged = true;
}
if (GUILayout.Button("Del")) {
Undo.RecordObject(prefabAsset, "Array delete " + prefabAsset.name);
receptor1.array.RemoveNucleus();
//receptor1.array.RemoveNucleus();
receptor1.RemoveReceptorElement();
anythingChanged = true;
}
EditorGUILayout.EndHorizontal();
@ -754,7 +756,7 @@ public class ClusterInspector : Editor {
anythingChanged |= newBias != this.currentNucleus.bias;
this.currentNucleus.bias = newBias;
NucleusArray array = null;
Nucleus[] array = null;
if (this.currentNucleus.synapses.Count > 0) {
Synapse[] synapses = this.currentNucleus.synapses.ToArray();
foreach (Synapse synapse in synapses) {
@ -762,16 +764,16 @@ public class ClusterInspector : Editor {
continue;
if (array != null) {
if (array.nuclei.Contains(synapse.nucleus))
if (array.Contains(synapse.nucleus))
continue;
if (array.nuclei.Contains(synapse.nucleus.parent))
if (array.Contains(synapse.nucleus.parent))
continue;
}
else {
if (synapse.nucleus.parent is ClusterReceptor clusterReceptor)
array = clusterReceptor.array;
array = clusterReceptor.nucleiArray;
else if (synapse.nucleus is Receptor receptor2) // && receptor2.array != null && receptor2.array.nuclei.Length > 1)
array = receptor2.array;
array = receptor2.nucleiArray;
}
EditorGUILayout.Space();
@ -832,7 +834,7 @@ public class ClusterInspector : Editor {
EditorGUILayout.EndHorizontal();
}
if (neuron is Receptor receptor2) {
if (receptor2.array == null || receptor2.array.nuclei == null || receptor2.array.nuclei.Count() == 0)
if (receptor2.nucleiArray == null || receptor2.nucleiArray.Count() == 0)
receptor2.array = new NucleusArray(neuron);
}
}
@ -877,7 +879,7 @@ public class ClusterInspector : Editor {
}
else {
if (this.currentNucleus is Receptor receptor1) {
foreach (Nucleus nucleus in receptor1.array.nuclei) {
foreach (Nucleus nucleus in receptor1.nucleiArray) {
Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue);
Handles.color = Color.yellow;
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);

View File

@ -3,9 +3,49 @@ using UnityEngine;
public interface IReceptor {
public string GetName();
public NucleusArray array {
get; set;
// public NucleusArray array {
// get; set;
// }
public Nucleus[] nucleiArray { get; set; }
public void AddReceptorElement(ClusterPrefab prefab);
public void RemoveReceptorElement();
public void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null);
}
public static class IReceptorHelpers {
public static Nucleus[] AddReceptorElement(Nucleus[] nucleiArray, ClusterPrefab prefab) {
if (nucleiArray.Length == 0) {
Debug.LogError("Empty perceptoid array, cannot add");
return null;
}
int newLength = nucleiArray.Length + 1;
Nucleus[] newArray = new Nucleus[newLength];
for (int i = 0; i < nucleiArray.Length; i++)
newArray[i] = nucleiArray[i];
if (nucleiArray[0] is Nucleus nucleus) {
newArray[newLength - 1] = nucleus.Clone(prefab);
newArray[newLength - 1].name += $": {newLength - 1}";
}
return newArray;
}
public void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName =null);
public static Nucleus[] RemoveReceptorElement(Nucleus[] nucleiArray) {
int newLength = nucleiArray.Length - 1;
if (newLength == 0) {
Debug.LogWarning("Perceptoid array cannot be empty");
return null;
}
Nucleus[] newPerceptei = new Nucleus[newLength];
for (int i = 0; i < newLength; i++)
newPerceptei[i] = nucleiArray[i];
// Delete the last perception
if (nucleiArray[newLength] is Nucleus nucleus)
Neuron.Delete(nucleus); //this._nuclei[newLength]);
return newPerceptei;
}
}

View File

@ -295,7 +295,7 @@ public class Neuron : Nucleus {
public virtual void RemoveReceiver(Nucleus receiverToRemove) {
if (this is IReceptor receptor) {
foreach (Nucleus element in receptor.array.nuclei) {
foreach (Nucleus element in receptor.nucleiArray) {
if (element is Neuron neuron) {
neuron._receivers.RemoveAll(receiver => receiver == receiverToRemove);
receiverToRemove.synapses.RemoveAll(synapse => synapse.nucleus == neuron);

View File

@ -12,6 +12,9 @@ public class NucleusArray {
get {
return _nuclei;
}
set {
_nuclei = value;
}
}
public NucleusArray(Nucleus nucleus) {
@ -68,7 +71,7 @@ public class NucleusArray {
float inputMagnitude = length(inputValue);
Nucleus selectedReceiver = null;
float selectedMagnitude = 0;
foreach (Nucleus receiver in this.nuclei) {
foreach (Nucleus receiver in this._nuclei) {
if (thingReceivers.ContainsValue(receiver) == false) {
// We found an unusued receiver
thingReceivers.Add(thingId, receiver);

View File

@ -5,12 +5,12 @@ using static Unity.Mathematics.math;
[System.Serializable]
public class Receptor : Neuron, IReceptor {
public Receptor(Cluster parent, string name) : base(parent, name) {
this.array ??= new NucleusArray(this);
this.array = new NucleusArray(this);
if (this.name.IndexOf(":") < 0)
this.name += ": 0";
}
public Receptor(ClusterPrefab prefab, string name) : base(prefab, name) {
this.array ??= new NucleusArray(this);
this.array = new NucleusArray(this);
}
public string GetName() {
@ -26,7 +26,7 @@ public class Receptor : Neuron, IReceptor {
}
public override Nucleus Clone(ClusterPrefab prefab) {
Receptor clone = new(prefab, name) {
array = this.array
array = this._array
};
CloneFields(clone);
// Adding receivers will also add synapses to the receivers
@ -39,12 +39,24 @@ public class Receptor : Neuron, IReceptor {
[SerializeReference]
private NucleusArray _array;
public NucleusArray array {
get { return _array; }
set { _array = value; }
}
public Nucleus[] nucleiArray {
get { return _array.nuclei; }
set { _array.nuclei = value; }
}
public void AddReceptorElement(ClusterPrefab prefab) {
this.nucleiArray = IReceptorHelpers.AddReceptorElement(this.nucleiArray, prefab);
}
public void RemoveReceptorElement() {
this.nucleiArray = IReceptorHelpers.RemoveReceptorElement(this.nucleiArray);
}
public virtual void AddArrayReceiver(Nucleus receiverToAdd, float weight = 1) {
foreach (Nucleus element in this.array.nuclei) {
foreach (Nucleus element in this._array.nuclei) {
if (element is Neuron neuron) {
neuron.AddReceiver(receiverToAdd, weight);
}
@ -65,7 +77,7 @@ public class Receptor : Neuron, IReceptor {
}
public virtual void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) {
this.array ??= new NucleusArray(this.parent);
this.array.ProcessStimulus(thingId, inputValue, thingName);
this._array ??= new NucleusArray(this.parent);
this._array.ProcessStimulus(thingId, inputValue, thingName);
}
}