Fixed cluster outputs

This commit is contained in:
Pascal Serrarens 2026-05-19 14:22:13 +02:00
parent ebef711981
commit 2a9693acca
6 changed files with 25 additions and 185 deletions

View File

@ -3,7 +3,6 @@ using System.Linq;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements;
namespace NanoBrain.Unity { namespace NanoBrain.Unity {
@ -53,151 +52,6 @@ namespace NanoBrain.Unity {
EditorGUILayout.EndHorizontal(); // end split EditorGUILayout.EndHorizontal(); // end split
} }
// public override void OnInspectorGUI() {
// float totalWidth = EditorGUIUtility.currentViewWidth;
// float leftW = drawAreaWidth;
// float rightW = Mathf.Max(80f, totalWidth - leftW - padding);
// Rect row = GUILayoutUtility.GetRect(totalWidth, 450f); // request full width
// Rect leftRect = new Rect(row.x, row.y, leftW, row.height);
// Rect rightRect = new Rect(row.x + leftW + padding, row.y, rightW, 450f);
// Rect innerLeft = new Rect(leftRect.x + padding, leftRect.y + padding,
// leftRect.width - padding*2, leftRect.height - padding*2);
// clusterView.Render(innerLeft);
// GUILayout.BeginArea(rightRect);
// float prev = EditorGUIUtility.labelWidth;
// EditorGUIUtility.labelWidth = 100f;
// InspectorHandler(serializedObject);
// EditorGUIUtility.labelWidth = prev;
// GUILayout.EndArea();
// }
//}
/*
public class ClusterEditor : ClusterViewer {
public override VisualElement CreateInspectorGUI() {
ClusterPrefab prefab = target as ClusterPrefab;
if (prefab != null)
prefab.EnsureInitialization();
serializedObject.Update();
VisualElement root = new();
CreateEditor(root, prefab, null);
serializedObject.ApplyModifiedProperties();
return root;
}
public GraphView CreateEditor(VisualElement root, ClusterPrefab cluster, GameObject gameObject) {
root.style.paddingLeft = 0;
root.style.paddingRight = 0;
root.style.paddingTop = 0;
root.style.paddingBottom = 0;
root.styleSheets.Add(Resources.Load<StyleSheet>("GraphStyles"));
VisualElement mainContainer = new() {
style = {
flexDirection = FlexDirection.Row,
}
};
GraphEditor graphContainer = new(cluster);
graphContainer.style.flexShrink = 0;
graphContainer.style.width = 300;
graphContainer.style.overflow = Overflow.Hidden;
VisualElement inspectorContainer = new() {
name = "inspector",
style = {
minHeight = 450,
width = 300,
flexGrow = 0,
flexDirection = FlexDirection.Row,
}
};
mainContainer.Add(graphContainer);
mainContainer.Add(inspectorContainer);
root.Add(mainContainer);
graphContainer.SetGraph(gameObject, inspectorContainer);
return graphContainer;
}
public class GraphEditor : GraphView {
protected ClusterPrefab prefab;
//protected Nucleus currentPrefabNucleus;
protected override Nucleus currentNucleus {
get => base.currentNucleus;
set {
base.currentNucleus = value;
// this.currentPrefabNucleus = value != null ? this.prefab.GetNucleus(value.name) : null;
}
}
public GraphEditor(ClusterPrefab prefab) : base(prefab.cluster.defaultOutput.parent) {
this.prefab = prefab;
// In a Prefab editor, no instance exists but we need it for the ClusterViewer.
// So we create a temporary instance
//this.currentCluster = new(prefab);
this.currentCluster = prefab.cluster;
this.currentCluster.Refresh();
}
public void SetGraph(GameObject gameObject, VisualElement inspectorContainer) {
this.gameObject = gameObject;
if (Application.isPlaying == false)
this.serializedBrain = new SerializedObject(this.prefab);
this.selectedOutput = this.currentCluster.defaultOutput;
this.currentNucleus = this.selectedOutput;
//this.currentCluster = this.currentNucleus.parent;
Rebuild(inspectorContainer);
// if (outputsPopup != null)
// OnOutputChanged(outputsPopup.choices[0]);
}
private void Rebuild(VisualElement inspectorContainer) {
if (this.currentNucleus == null) {
inspectorContainer.Clear();
return;
}
string path = AssetDatabase.GetAssetPath(this.prefab); // or known path
this.prefabAsset = AssetDatabase.LoadAssetAtPath<ClusterPrefab>(path);
if (this.prefabAsset == null) {
// create in memory save if it doesn't exist
this.prefabAsset = CreateInstance<ClusterPrefab>();
//Debug.LogError("Cluster Prefab is not found on disk");
}
// DrawInspector(inspectorContainer);
if (inspectorContainer == null)
return;
inspectorContainer.Clear();
if (this.currentNucleus == null)
return;
// create a SerializedObject wrapper so Unity inspector controls work (and Undo)
SerializedObject so = new(prefabAsset);
// foreach (Nucleus nucleus in this.prefab.cluster.nuclei) {
// nucleus.Initialize();
// }
this.inspectorIMGUIContainer = new IMGUIContainer(() => InspectorHandler(so));
inspectorContainer.Add(inspectorIMGUIContainer);
}
*/
#region Inspector #region Inspector
//private VisualElement inspectorIMGUIContainer; //private VisualElement inspectorIMGUIContainer;
@ -336,9 +190,9 @@ namespace NanoBrain.Unity {
protected void SynapsesInspector(ref bool anythingChanged) { protected void SynapsesInspector(ref bool anythingChanged) {
EditorGUI.indentLevel++; EditorGUI.indentLevel++;
//showSynapses = EditorGUILayout.BeginFoldoutHeaderGroup(showSynapses, "Synapses"); showSynapses = EditorGUILayout.Foldout(showSynapses, "Synapses", true);
showSynapses = EditorGUILayout.Foldout(showSynapses, "Synapses");
if (showSynapses) { if (showSynapses) {
EditorGUI.indentLevel--;
if (this.currentNucleus is Neuron neuron2) { if (this.currentNucleus is Neuron neuron2) {
Neuron.CombinatorType newCombinator = (Neuron.CombinatorType)EditorGUILayout.EnumPopup("Combinator", neuron2.combinator); Neuron.CombinatorType newCombinator = (Neuron.CombinatorType)EditorGUILayout.EnumPopup("Combinator", neuron2.combinator);
anythingChanged |= newCombinator != neuron2.combinator; anythingChanged |= newCombinator != neuron2.combinator;
@ -441,8 +295,8 @@ namespace NanoBrain.Unity {
anythingChanged |= ConnectNucleus(this.clusterPrefab, this.currentNucleus); anythingChanged |= ConnectNucleus(this.clusterPrefab, this.currentNucleus);
anythingChanged |= AddSynapse(this.clusterPrefab, this.currentNucleus); anythingChanged |= AddSynapse(this.clusterPrefab, this.currentNucleus);
} }
//EditorGUILayout.EndFoldoutHeaderGroup(); else
EditorGUI.indentLevel--; EditorGUI.indentLevel--;
} }
@ -451,6 +305,7 @@ namespace NanoBrain.Unity {
EditorGUI.indentLevel++; EditorGUI.indentLevel++;
showActivation = EditorGUILayout.Foldout(showActivation, "Activation"); showActivation = EditorGUILayout.Foldout(showActivation, "Activation");
if (showActivation) { if (showActivation) {
EditorGUI.indentLevel--;
if (this.currentNucleus is Neuron neuron) { if (this.currentNucleus is Neuron neuron) {
if (this.currentNucleus is not MemoryCell) { if (this.currentNucleus is not MemoryCell) {
EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginHorizontal();
@ -472,8 +327,8 @@ namespace NanoBrain.Unity {
EditorGUILayout.Space(); EditorGUILayout.Space();
} }
//EditorGUILayout.EndFoldoutHeaderGroup(); else
EditorGUI.indentLevel--; EditorGUI.indentLevel--;
} }
#region Synapses #region Synapses

View File

@ -62,30 +62,13 @@ namespace NanoBrain.Unity {
Rect drawRect = new(fieldRect.x, headerRect.yMax + 2f, fieldRect.width, 450f); Rect drawRect = new(fieldRect.x, headerRect.yMax + 2f, fieldRect.width, 450f);
ClusterView.Render(drawRect, prefab.cluster, property); ClusterView.Render(drawRect, prefab.cluster, property);
//Debug.Log(prefab.cluster.defaultOutput.outputMagnitude);
} }
} }
EditorGUI.indentLevel = indent; EditorGUI.indentLevel = indent;
EditorGUI.EndProperty(); EditorGUI.EndProperty();
} }
// public ClusterViewer.GraphView CreateViewer(Cluster cluster, GameObject gameObject) {
// VisualElement mainContainer = new() {
// style = {
// flexDirection = FlexDirection.Row,
// minHeight = 450
// }
// };
// ClusterViewer.GraphView graph = new(cluster);
// graph.style.flexGrow = 1;
// mainContainer.Add(graph);
// root.Add(mainContainer);
// graph.SetGraph(gameObject);
// return graph;
// }
} }
/* /*

View File

@ -82,8 +82,8 @@ namespace NanoBrain.Unity {
Vector3 position = new(150, 210, 0); Vector3 position = new(150, 210, 0);
if (this.currentNucleus != null) { if (this.currentNucleus != null) {
DrawReceivers(this.currentNucleus, position, size); DrawReceivers(this.currentNucleus, position);
DrawSynapses(this.currentNucleus, position, size); DrawSynapses(this.currentNucleus, position);
// Draw selected Nucleus // Draw selected Nucleus
if (this.expandArray) { if (this.expandArray) {
@ -152,6 +152,7 @@ namespace NanoBrain.Unity {
maxValue = neuron.outputMagnitude; maxValue = neuron.outputMagnitude;
else if (this.currentNucleus is Cluster cluster) else if (this.currentNucleus is Cluster cluster)
maxValue = cluster.defaultOutput.outputMagnitude; maxValue = cluster.defaultOutput.outputMagnitude;
Debug.Log($"Neuron {maxValue} {currentCluster.defaultOutput.outputMagnitude}");
DrawNucleus(this.currentNucleus, position, maxValue); DrawNucleus(this.currentNucleus, position, maxValue);
} }
} }
@ -161,7 +162,7 @@ namespace NanoBrain.Unity {
} }
} }
protected void DrawReceivers(Nucleus nucleus, Vector3 parentPos, float size) { protected void DrawReceivers(Nucleus nucleus, Vector3 parentPos) {
List<Nucleus> receivers; List<Nucleus> receivers;
if (nucleus is Neuron neuron) if (nucleus is Neuron neuron)
receivers = neuron.receivers; receivers = neuron.receivers;
@ -220,7 +221,7 @@ namespace NanoBrain.Unity {
} }
} }
protected void DrawSynapses(Nucleus nucleus, Vector3 parentPos, float size) { protected void DrawSynapses(Nucleus nucleus, Vector3 parentPos) {
if (nucleus is not Neuron neuron) if (nucleus is not Neuron neuron)
return; return;

View File

@ -366,6 +366,7 @@ namespace NanoBrain {
/// <summary> /// <summary>
/// This gives the order in which nuclei should be computed when a nucleus is updated /// This gives the order in which nuclei should be computed when a nucleus is updated
/// </summary> /// </summary>
[NonSerialized]
private Dictionary<Nucleus, List<Nucleus>> _computeOrders; private Dictionary<Nucleus, List<Nucleus>> _computeOrders;
/// <summary> /// <summary>
/// This gives the order in which nuclei should be computed when a nucleus is updated /// This gives the order in which nuclei should be computed when a nucleus is updated
@ -464,6 +465,7 @@ namespace NanoBrain {
/// The neurons without outgoing connections /// The neurons without outgoing connections
/// </summary> /// </summary>
/// These neurons can potentially be connected to neurons in other clusters /// These neurons can potentially be connected to neurons in other clusters
[NonSerialized]
protected List<Neuron> _outputs = null; protected List<Neuron> _outputs = null;
/// <summary> /// <summary>
/// The neurons without outgoing connections /// The neurons without outgoing connections

View File

@ -31,12 +31,12 @@ MonoBehaviour:
data: data:
name: Output name: Output
parent: parent:
rid: 4201950130928878123 rid: 4201950148723474519
bias: {x: 0, y: 0, z: 1} bias: {x: 0, y: 0, z: 1}
_synapses: _synapses:
- neuron: - neuron:
rid: 4201949899492425817 rid: 4201949899492425817
weight: 5 weight: 4
combinator: 0 combinator: 0
_activator: 0 _activator: 0
curve: curve:
@ -65,15 +65,15 @@ MonoBehaviour:
m_RotationOrder: 4 m_RotationOrder: 4
curveMax: 1 curveMax: 1
persistOutput: 0 persistOutput: 0
lastUpdate: 16.366629 lastUpdate: 14.822748
_receivers: [] _receivers: []
- rid: 4201949899492425817 - rid: 4201949899492425817
type: {class: Neuron, ns: NanoBrain, asm: Assembly-CSharp} type: {class: Neuron, ns: NanoBrain, asm: Assembly-CSharp}
data: data:
name: Sensor name: Sensor
parent: parent:
rid: 4201950130928878123 rid: 4201950148723474519
bias: {x: 0.061416026, y: 0.061416026, z: 0.061416026} bias: {x: 0.062121756, y: 0.062121756, z: 0.062121756}
_synapses: [] _synapses: []
combinator: 0 combinator: 0
_activator: 0 _activator: 0
@ -103,10 +103,10 @@ MonoBehaviour:
m_RotationOrder: 4 m_RotationOrder: 4
curveMax: 1 curveMax: 1
persistOutput: 0 persistOutput: 0
lastUpdate: 16.366629 lastUpdate: 14.822748
_receivers: _receivers:
- rid: 4201949899492425781 - rid: 4201949899492425781
- rid: 4201950130928878123 - rid: 4201950148723474519
type: {class: Cluster, ns: NanoBrain, asm: Assembly-CSharp} type: {class: Cluster, ns: NanoBrain, asm: Assembly-CSharp}
data: data:
name: Braitenberg 1 name: Braitenberg 1

View File

@ -15,10 +15,9 @@ namespace NanoBrain.Braitenberg {
public Sensor sensorRight; public Sensor sensorRight;
void FixedUpdate() { void FixedUpdate() {
//Debug.Log($"L: {sensorLeft.output} R: {sensorRight.output}"); // //Debug.Log($"L: {sensorLeft.output} R: {sensorRight.output}");
//Debug.Log($"L: {motorLeft.speed} R: {motorRight.speed}"); // //Debug.Log($"L: {motorLeft.speed} R: {motorRight.speed}");
Debug.Log($"L: {motorLeft.wheelCollider.rpm} R: {motorRight.wheelCollider.rpm}"); // Debug.Log($"L: {motorLeft.wheelCollider.rpm} R: {motorRight.wheelCollider.rpm}");
} }
} }