WIP: cloning of nucleusarrays is not working yet

This commit is contained in:
Pascal Serrarens 2026-02-04 17:42:16 +01:00
parent 60e2b3e33f
commit 3cc5f56f61
6 changed files with 89 additions and 46 deletions

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEngine; using UnityEngine;
using Unity.Mathematics; using Unity.Mathematics;
using static Unity.Mathematics.math; using static Unity.Mathematics.math;
@ -51,22 +52,22 @@ public class Cluster : INucleus {
// } // }
private void ClonePrefab() { private void ClonePrefab() {
IReceptor[] nucleiArray = this.prefab.nuclei.ToArray(); IReceptor[] nuclei = this.prefab.nuclei.ToArray();
// first clone the nuclei without their connections // first clone the nuclei without their connections
foreach (IReceptor nucleus in this.prefab.nuclei) foreach (IReceptor nucleus in this.prefab.nuclei)
nucleus.ShallowCloneTo(this); nucleus.ShallowCloneTo(this);
IReceptor[] clonedNuclei = this.nuclei.ToArray(); IReceptor[] clonedNuclei = this.nuclei.ToArray();
// Now clone the connections // Now clone the connections
for (int nucleusIx = 0; nucleusIx < nucleiArray.Length; nucleusIx++) { for (int nucleusIx = 0; nucleusIx < nuclei.Length; nucleusIx++) {
IReceptor receptor = nucleiArray[nucleusIx]; IReceptor receptor = nuclei[nucleusIx];
IReceptor clonedSender = clonedNuclei[nucleusIx]; IReceptor clonedSender = clonedNuclei[nucleusIx];
if (clonedSender == null) if (clonedSender == null)
continue; continue;
// Copy the receivers, which will also create the synapses // Copy the receivers, which will also create the synapses
foreach (INucleus receiver in receptor.receivers) { foreach (INucleus receiver in receptor.receivers) {
int ix = GetNucleusIndex(nucleiArray, receiver); int ix = GetNucleusIndex(nuclei, receiver);
if (ix < 0) if (ix < 0)
continue; continue;
@ -75,15 +76,42 @@ public class Cluster : INucleus {
// Find the synapse for the weight // Find the synapse for the weight
float weight = 1; float weight = 1;
NucleusArray nucleusArray = null;
foreach (Synapse synapse in receiver.synapses) { foreach (Synapse synapse in receiver.synapses) {
if (synapse.nucleus == receptor) { if (synapse.nucleus == receptor)
weight = synapse.weight; weight = synapse.weight;
break; if (synapse.nucleus is INucleus synapseNucleus) {
if (synapseNucleus.array != null && synapseNucleus.array.nuclei.Length > 0) {
if (nucleusArray == null) {
// copy the array
nucleusArray = new NucleusArray(synapseNucleus.array.nuclei.Length, "array");
for (int arrayIx = 0; arrayIx < synapseNucleus.array.nuclei.Length; arrayIx++) {
IReceptor arrayNucleus = synapseNucleus.array.nuclei[arrayIx];
int ix2 = GetNucleusIndex(nuclei, arrayNucleus);
nucleusArray.nuclei[arrayIx] = clonedNuclei[ix2];
}
}
synapseNucleus.array = nucleusArray;
}
} }
} }
clonedSender.AddReceiver(clonedReceiver, weight); clonedSender.AddReceiver(clonedReceiver, weight);
} }
// if (receptor is INucleus nucleus) {
// if (clonedSender is not INucleus clonedNucleus) {
// Debug.LogError("INucleus clone is not an INucleus!");
// continue;
// }
// clonedNucleus.array = new NucleusArray(nucleus.array._nuclei.Length, "array");
// for (int arrayIx = 0; arrayIx < nucleus.array._nuclei.Length; arrayIx++) {
// //foreach (INucleus arrayNucleus in nucleus.array.nuclei) {
// IReceptor arrayNucleus = nucleus.array._nuclei[arrayIx];
// int ix = GetNucleusIndex(nuclei, arrayNucleus);
// clonedNucleus.array._nuclei[arrayIx] = clonedNuclei[ix];
// }
// }
} }
} }

View File

@ -210,7 +210,7 @@ public class ClusterInspector : Editor {
// Draw selected Nucleus // Draw selected Nucleus
if (expandArray) { if (expandArray) {
float maxValue = 0; float maxValue = 0;
foreach (INucleus nucleus in this.currentNucleus.array.nuclei) { foreach (IReceptor nucleus in this.currentNucleus.array.nuclei) {
float value = length(nucleus.outputValue); float value = length(nucleus.outputValue);
if (value > maxValue) if (value > maxValue)
maxValue = value; maxValue = value;
@ -231,7 +231,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 (INucleus nucleus in this.currentNucleus.array.nuclei) { foreach (IReceptor nucleus in this.currentNucleus.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
@ -239,13 +239,13 @@ public class ClusterInspector : Editor {
DrawNucleus(nucleus, pos, maxValue, size); DrawNucleus(nucleus, pos, maxValue, size);
row++; row++;
} }
GUIStyle style = new(EditorStyles.label) { // GUIStyle style = new(EditorStyles.label) {
alignment = TextAnchor.UpperCenter, // alignment = TextAnchor.UpperCenter,
normal = { textColor = Color.white }, // normal = { textColor = Color.white },
fontStyle = FontStyle.Bold, // fontStyle = FontStyle.Bold,
}; // };
Vector3 labelPos = new Vector3(150, yMax, 0) - Vector3.down * (size + 10); // below disc along up axis // Vector3 labelPos = new Vector3(150, yMax, 0) - Vector3.down * (size + 25); // below disc along up axis
Handles.Label(labelPos, this.currentNucleus.name, style); // Handles.Label(labelPos, this.currentNucleus.name, style);
} }
else { else {
Handles.color = Color.white; Handles.color = Color.white;
@ -274,7 +274,12 @@ public class ClusterInspector : Editor {
float margin = 10 + spacing / 2; float margin = 10 + spacing / 2;
int row = 0; int row = 0;
List<NucleusArray> drawnArrays = new();
foreach (INucleus receiver in nucleus.receivers) { foreach (INucleus receiver in nucleus.receivers) {
if (drawnArrays.Contains(receiver.array))
continue;
drawnArrays.Add(receiver.array);
INucleus receiverNucleus = receiver; INucleus receiverNucleus = receiver;
if (receiverNucleus == null) if (receiverNucleus == null)
continue; continue;

View File

@ -13,17 +13,22 @@ public class NanoBrain : MonoBehaviour {
name = defaultBrain.name + " (Instance)" name = defaultBrain.name + " (Instance)"
}; };
} }
SwarmControl sc = FindFirstObjectByType<SwarmControl>(); // SwarmControl sc = FindFirstObjectByType<SwarmControl>();
if (sc != null) { // if (sc != null) {
UpdateWeight(brainInstance, "Containment", sc.containmentForce); // UpdateWeight(brainInstance, "Containment", sc.containmentForce);
UpdateWeight(brainInstance, "Cohesion", sc.cohesionForce); // UpdateWeight(brainInstance, "Cohesion", sc.cohesionForce);
UpdateWeight(brainInstance, "Separation", sc.separationForce); // UpdateWeight(brainInstance, "Separation", sc.separationForce);
UpdateWeight(brainInstance, "Alignment", sc.alignmentForce); // UpdateWeight(brainInstance, "Alignment", sc.alignmentForce);
} // }
return brainInstance; return brainInstance;
} }
} }
// public void Awake() {
// brainInstance = new Cluster(defaultBrain);
// }
public static void UpdateWeight(Cluster brain, string name, float weight) { public static void UpdateWeight(Cluster brain, string name, float weight) {
INucleus root = brain.output; INucleus root = brain.output;
foreach (Synapse synapse in root.synapses) { foreach (Synapse synapse in root.synapses) {

View File

@ -183,7 +183,7 @@ public class Neuron : INucleus {
// this clone the nucleus without the synapses and receivers // this clone the nucleus without the synapses and receivers
public virtual IReceptor ShallowCloneTo(Cluster newParent) { public virtual IReceptor ShallowCloneTo(Cluster newParent) {
Neuron clone = new(newParent, this.name) { Neuron clone = new(newParent, this.name) {
array = this.array, array = null,
curve = this.curve, curve = this.curve,
curvePreset = this.curvePreset, curvePreset = this.curvePreset,
curveMax = this.curveMax, curveMax = this.curveMax,

View File

@ -5,16 +5,11 @@ using UnityEngine;
[System.Serializable] [System.Serializable]
public class NucleusArray { public class NucleusArray {
[SerializeReference] [SerializeReference]
private INucleus[] _nuclei; private IReceptor[] _nuclei;
private ClusterPrefab[] _clusters; //private ClusterPrefab[] _clusters;
public IEnumerable<INucleus> nuclei { public IReceptor[] nuclei {
get { get {
// if (_nuclei == null)
// return _clusters;
// else if (_clusters == null)
return _nuclei; return _nuclei;
// else
// return _nuclei.Concat(_clusters);
} }
} }
public string name; public string name;
@ -23,14 +18,19 @@ public class NucleusArray {
this.name = nucleus.name; this.name = nucleus.name;
this._nuclei = new INucleus[1]; this._nuclei = new INucleus[1];
this._nuclei[0] = nucleus; this._nuclei[0] = nucleus;
this._clusters = new ClusterPrefab[0]; //this._clusters = new ClusterPrefab[0];
} }
public NucleusArray(ClusterPrefab cluster) { public NucleusArray(ClusterPrefab cluster) {
this.name = cluster.name; this.name = cluster.name;
this._nuclei = new INucleus[0]; this._nuclei = new INucleus[0];
this._clusters = new ClusterPrefab[1]; // this._clusters = new ClusterPrefab[1];
this._clusters[0] = cluster; // this._clusters[0] = cluster;
} }
public NucleusArray(int size, string name) {
this.name = name;
this._nuclei = new INucleus[size];
}
public void AddNucleus() { public void AddNucleus() {
if (this._nuclei.Length == 0) { if (this._nuclei.Length == 0) {
@ -38,7 +38,7 @@ public class NucleusArray {
return; return;
} }
int newLength = this._nuclei.Length + 1; int newLength = this._nuclei.Length + 1;
INucleus[] newArray = new INucleus[newLength]; IReceptor[] newArray = new INucleus[newLength];
for (int i = 0; i < this._nuclei.Length; i++) for (int i = 0; i < this._nuclei.Length; i++)
newArray[i] = this._nuclei[i]; newArray[i] = this._nuclei[i];
@ -54,11 +54,12 @@ public class NucleusArray {
Debug.LogWarning("Perceptoid array cannot be empty"); Debug.LogWarning("Perceptoid array cannot be empty");
return; return;
} }
INucleus[] newPerceptei = new INucleus[newLength]; IReceptor[] newPerceptei = new INucleus[newLength];
for (int i = 0; i < newLength; i++) for (int i = 0; i < newLength; i++)
newPerceptei[i] = this._nuclei[i]; newPerceptei[i] = this._nuclei[i];
// Delete the last perception // Delete the last perception
Neuron.Delete(this._nuclei[newLength]); if (this._nuclei[newLength] is INucleus nucleus)
Neuron.Delete(nucleus); //this._nuclei[newLength]);
this._nuclei = newPerceptei; this._nuclei = newPerceptei;
} }

View File

@ -6,8 +6,6 @@ using static Unity.Mathematics.math;
public class Receptor : IReceptor { public class Receptor : IReceptor {
private ClusterPrefab cluster;
private Cluster parent;
[SerializeField] [SerializeField]
protected string _name; protected string _name;
@ -63,6 +61,9 @@ public class Receptor : IReceptor {
// return receptor; // return receptor;
} }
private ClusterPrefab cluster;
private Cluster parent;
public virtual IReceptor ShallowCloneTo(Cluster parent) { public virtual IReceptor ShallowCloneTo(Cluster parent) {
Receptor clone = new(parent); Receptor clone = new(parent);
return clone; return clone;
@ -188,7 +189,9 @@ public class Receptor : IReceptor {
} }
receiverIx++; receiverIx++;
} }
Debug.Log($"Receiver {selectedReceiver.name}[{selectedReceiverIx}] for thing {thingId}"); if (selectedReceiverIx >= thingIds.Length)
return;
thingIds[selectedReceiverIx] = thingId; thingIds[selectedReceiverIx] = thingId;
if (thingName != null) { if (thingName != null) {
string baseName = selectedReceiver.name; string baseName = selectedReceiver.name;
@ -197,6 +200,7 @@ public class Receptor : IReceptor {
baseName = selectedReceiver.name.Substring(0, colonPos); baseName = selectedReceiver.name.Substring(0, colonPos);
selectedReceiver.name = baseName + ": " + thingName; selectedReceiver.name = baseName + ": " + thingName;
} }
Debug.Log($"Receiver {selectedReceiver.name}[{selectedReceiverIx}] for thing {thingId}");
selectedReceiver.parent.UpdateStateIsolated(); selectedReceiver.parent.UpdateStateIsolated();
} }