Fix links to multiple cluster neurons & cleanup

This commit is contained in:
Pascal Serrarens 2026-04-22 12:44:36 +02:00
parent e17a249743
commit 04bab9264f
3 changed files with 99 additions and 115 deletions

View File

@ -153,15 +153,11 @@ namespace NanoBrain {
fontStyle = FontStyle.Bold
};
// Nucleus type
string nucleusType = this.currentNucleus.GetType().Name;
// if (this.currentNucleus.parent != null) {
// string clusterName = this.currentNucleus.parent.name;
// GUILayout.Label(clusterName + ": " + nucleusType, headerStyle);
// }
// else
GUILayout.Label(nucleusType, headerStyle);
// Nucleus name
if (this.currentNucleus.parent is Cluster parentCluster) {
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(this.currentNucleus.parent.name))
@ -183,6 +179,7 @@ namespace NanoBrain {
}
}
// Current output value
if (Application.isPlaying) {
if (currentNucleus is Neuron currentNeuron1) {
GUIContent nameLabel = new("Output", currentNeuron1.outputValue.ToString());
@ -194,44 +191,63 @@ namespace NanoBrain {
else
EditorGUILayout.LabelField(" ");
if (this.currentNucleus is MemoryCell memory) {
memory.staticMemory = EditorGUILayout.Toggle("Static Memory", memory.staticMemory);
}
// Memory cell
if (this.currentNucleus is MemoryCell memory)
MemoryCellInspector(memory, ref anythingChanged);
// Cluster
else if (this.currentNucleus is Cluster cluster)
ClusterInspector(cluster, ref anythingChanged);
// Other
else
NucleusInspector(this.currentNucleus, ref anythingChanged);
if (this.currentNucleus is Cluster cluster) {
EditorGUILayout.BeginHorizontal();
if (cluster.instanceCount > 1)
EditorGUILayout.IntField("Array size", cluster.instanceCount, GUILayout.MinWidth(150));
else if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1)
EditorGUILayout.IntField("Array size", cluster.siblingClusters.Count(), GUILayout.MinWidth(150));
else
EditorGUILayout.IntField("Array size", 1, GUILayout.MinWidth(150));
if (GUILayout.Button("Add")) {
Undo.RecordObject(prefabAsset, "Array add " + prefabAsset.name);
//cluster.AddInstance(this.prefab);
cluster.AddInstance();
anythingChanged = true;
}
if (GUILayout.Button("Del")) {
Undo.RecordObject(prefabAsset, "Array delete " + prefabAsset.name);
cluster.RemoveInstance();
anythingChanged = true;
}
EditorGUILayout.EndHorizontal();
}
SynapsesInspector(ref anythingChanged);
ActivationInspector(ref anythingChanged);
if (GUILayout.Button("Delete this neuron"))
if (GUILayout.Button("Delete"))
DeleteNucleus(this.currentNucleus);
if (this.currentNucleus is Cluster subCluster) {
if (GUILayout.Button("Reimport Cluster"))
ReimportCluster(subCluster);
if (GUILayout.Button("Edit Cluster"))
EditCluster(subCluster);
serializedObject.ApplyModifiedProperties();
if (anythingChanged) {
EditorUtility.SetDirty(prefabAsset);
AssetDatabase.SaveAssets();
}
}
protected void MemoryCellInspector(MemoryCell memoryCell, ref bool anythingChanged) {
memoryCell.staticMemory = EditorGUILayout.Toggle("Static Memory", memoryCell.staticMemory);
NucleusInspector(memoryCell, ref anythingChanged);
}
protected void ClusterInspector(Cluster cluster, ref bool anythingChanged) {
EditorGUILayout.BeginHorizontal();
int instanceCount = cluster.instanceCount;
if (instanceCount <= 1) {
if (cluster.siblingClusters != null && cluster.siblingClusters.Length > 1)
instanceCount = cluster.siblingClusters.Count();
else
instanceCount = 1;
}
EditorGUILayout.IntField("Instances", instanceCount, GUILayout.MinWidth(150));
if (GUILayout.Button("Add")) {
Undo.RecordObject(prefabAsset, "Array add " + prefabAsset.name);
//cluster.AddInstance(this.prefab);
cluster.AddInstance();
anythingChanged = true;
}
if (GUILayout.Button("Del")) {
Undo.RecordObject(prefabAsset, "Array delete " + prefabAsset.name);
cluster.RemoveInstance();
anythingChanged = true;
}
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("Reimport Cluster"))
ReimportCluster(cluster);
}
protected void NucleusInspector(Nucleus nucleus, ref bool anythingChanged) {
SynapsesInspector(ref anythingChanged);
ActivationInspector(ref anythingChanged);
EditorGUILayout.Space();
breakOnWake = EditorGUILayout.Toggle("Break on wake", breakOnWake);
@ -242,11 +258,6 @@ namespace NanoBrain {
trace = EditorGUILayout.Toggle("Trace", trace);
this.currentNucleus.trace = trace;
serializedObject.ApplyModifiedProperties();
if (anythingChanged) {
EditorUtility.SetDirty(prefabAsset);
AssetDatabase.SaveAssets();
}
}
protected void SynapsesInspector(ref bool anythingChanged) {
@ -361,35 +372,31 @@ namespace NanoBrain {
}
protected void ActivationInspector(ref bool anythingChanged) {
if (this.currentNucleus is not Cluster) {
EditorGUILayout.Space();
showActivation = EditorGUILayout.BeginFoldoutHeaderGroup(showActivation, "Activation");
if (showActivation) {
if (this.currentNucleus is Neuron neuron) {
if (this.currentNucleus is not MemoryCell) {
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Activation Curve", GUILayout.MinWidth(60));
if (neuron.curveMax > 0)
EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, 0, 1, neuron.curveMax), GUILayout.Width(40));
else
EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, neuron.curveMax, 1, -neuron.curveMax), GUILayout.Width(40));
Neuron.ActivationType newPreset = (Neuron.ActivationType)EditorGUILayout.EnumPopup(neuron.curvePreset, GUILayout.MinWidth(50));
anythingChanged |= newPreset != neuron.curvePreset;
neuron.curvePreset = newPreset;
EditorGUILayout.EndHorizontal();
}
// if (neuron is Receptor receptor2) {
// if (receptor2.nucleiArray == null || receptor2.nucleiArray.Count() == 0)
// receptor2.array = new NucleusArray(neuron);
// }
EditorGUILayout.Space();
showActivation = EditorGUILayout.BeginFoldoutHeaderGroup(showActivation, "Activation");
if (showActivation) {
if (this.currentNucleus is Neuron neuron) {
if (this.currentNucleus is not MemoryCell) {
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Activation Curve", GUILayout.MinWidth(60));
if (neuron.curveMax > 0)
EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, 0, 1, neuron.curveMax), GUILayout.Width(40));
else
EditorGUILayout.CurveField(neuron.curve, Color.cyan, new Rect(0, neuron.curveMax, 1, -neuron.curveMax), GUILayout.Width(40));
Neuron.ActivationType newPreset = (Neuron.ActivationType)EditorGUILayout.EnumPopup(neuron.curvePreset, GUILayout.MinWidth(50));
anythingChanged |= newPreset != neuron.curvePreset;
neuron.curvePreset = newPreset;
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.Space();
// if (neuron is Receptor receptor2) {
// if (receptor2.nucleiArray == null || receptor2.nucleiArray.Count() == 0)
// receptor2.array = new NucleusArray(neuron);
// }
}
EditorGUILayout.EndFoldoutHeaderGroup();
}
EditorGUILayout.Space();
}
EditorGUILayout.EndFoldoutHeaderGroup();
}
#region Synapses

View File

@ -447,28 +447,20 @@ namespace NanoBrain {
// This is used to 'scale' the output value colors of the nuclei
float maxValue = 0;
int neuronCount = 0;
//List<Nucleus[]> drawnArrays = new();
Cluster[] drawnCluster = null;
List<Neuron> drawnNeurons = new();
foreach (Synapse synapse in nucleus.synapses) {
if (synapse.neuron == null)
continue;
if (synapse.neuron.parent is Cluster cluster &&
//cluster.siblingClusters != null &&
synapse.neuron.parent != nucleus.parent) {
// Draw multiple synapses to the same neuron only once
if (drawnNeurons.Contains(synapse.neuron))
continue;
drawnNeurons.Add(synapse.neuron);
float value = synapse.neuron.outputMagnitude * synapse.weight;
if (value > maxValue)
maxValue = value;
//if (drawnArrays.Contains(cluster.siblingClusters))
if (drawnCluster is not null && cluster.SameSiblingsAs(drawnCluster))
continue;
//drawnArrays.Add(cluster.siblingClusters);
drawnCluster = cluster.siblingClusters;
}
if (synapse.neuron is Neuron synapseNeuron) {
float value = synapseNeuron.outputMagnitude * synapse.weight;
// Debug.Log($"{synapse.nucleus.name}: {value} {length(synapse.nucleus.outputValue)} {synapse.weight}");
if (value > maxValue)
maxValue = value;
}
neuronCount++;
}
@ -477,23 +469,15 @@ namespace NanoBrain {
float margin = 10 + spacing / 2;
int row = 0;
//drawnArrays = new();
drawnCluster = null;
drawnNeurons = new();
foreach (Synapse synapse in nucleus.synapses) {
if (synapse.neuron is null)
continue;
if (synapse.neuron.parent is Cluster cluster &&
//cluster.siblingClusters != null &&
synapse.neuron.parent != nucleus.parent) {
if (drawnNeurons.Contains(synapse.neuron))
continue;
drawnNeurons.Add(synapse.neuron);
// if (drawnArrays.Contains(cluster.siblingClusters))
// continue;
// drawnArrays.Add(cluster.siblingClusters);
if (drawnCluster is not null && cluster.SameSiblingsAs(drawnCluster))
continue;
drawnCluster = cluster.siblingClusters;
}
Vector3 pos = new(250, margin + row * spacing, 0.0f);
Handles.color = Color.white;
Handles.DrawLine(parentPos, pos);
@ -502,18 +486,10 @@ namespace NanoBrain {
if (maxValue == 0 || !float.IsFinite(maxValue))
maxValue = 1;
float brightness = 0;
if (synapse.neuron is Neuron synapseNeuron)
brightness = synapseNeuron.outputMagnitude * synapse.weight / maxValue;
brightness = synapse.neuron.outputMagnitude * synapse.weight / maxValue;
color = new Color(brightness, brightness, brightness, 1f);
}
if (synapse.neuron.parent != null && synapse.neuron.parent != this.currentNucleus.parent) {
// the synapse nucleus is part of a subcluster
//DrawNucleus(synapse.neuron.parent, pos, maxValue, size, color);
DrawNucleus(synapse.neuron, pos, size, color);
}
else {
DrawNucleus(synapse.neuron, pos, size, color);
}
DrawNucleus(synapse.neuron, pos, size, color);
row++;
}
}
@ -619,7 +595,7 @@ namespace NanoBrain {
}
}
private void DrawCluster(Cluster cluster, Vector3 position, Color color, float size) {
protected void DrawCluster(Cluster cluster, Vector3 position, Color color, float size) {
GUIStyle labelTextStyle = new(EditorStyles.label) {
normal = { textColor = Color.white },
fontStyle = FontStyle.Bold,
@ -704,7 +680,7 @@ namespace NanoBrain {
Handles.DrawLine(from, to);
}
private void HandleMouseHover(Nucleus nucleus, Rect rect) {
protected void HandleMouseHover(Nucleus nucleus, Rect rect) {
GUIContent tooltip;
if (nucleus is Neuron neuron) {
tooltip = new(

View File

@ -468,9 +468,10 @@ namespace NanoBrain {
}
public void AddArrayReceiver(Nucleus receiverToAdd, float weight = 1) {
foreach (Cluster cluster in this.siblingClusters) {
cluster.defaultOutput.AddReceiver(receiverToAdd, weight);
}
this.defaultOutput.AddReceiver(receiverToAdd, weight);
// foreach (Cluster cluster in this.siblingClusters) {
// cluster.defaultOutput.AddReceiver(receiverToAdd, weight);
// }
}